duangsuse::Echo
这就是一个正确的栗子,它给栈帧分配的是两个 dword 的空间,而上面那个是没有完成分配的任务,居然只给 64 位的东西分配 32 位的空间,读写都会冲突
执行时是怎么样的呢? 🤔(当然这里可能不严谨,不过也够了,反正大家很多人连 CDEF 系统栈是怎么维护的都不知道,也算是科普一下)
我们的 caller 叫做 main,它执行如下代码以调用我们的子程序 bd:
然后机器开始解释执行我们的程序逻辑:
==
; eip = *__x86_get_pc_thunk_bx
(其实就是拿到位于 .text 段的 ip 指针,也就是
(我们要重新用汇编重写的时候必须也重写这种 ebx 偏移量,把对它们的使用替换成 .rodata 段实际的偏移地址,NASM 可以帮我们做这件事,直接
; eip = *bd
; eax = *bd+5i
== 然后我们又回到了自己的程序
; GCC(GNU Compiler Collection) 4.9 是相当老的编译器了,不要忘记现在 GCC 都出 8 了
eax = my_arg2
eax = my_arg1
🤔所以,我们为什么要多分配这么多无用的东西?浪费了一个双字的空间(虽然 mov subarg2 的时候可能溢出到别的存储单元)
🤔
一瞬返回
最后 main 收拾调用现场
== main+???
对 bd 的调用就完成了(迫真)
我们的 caller 叫做 main,它执行如下代码以调用我们的子程序 bd:
sub esp, (2*4)<sp> [....] [....] |*****
mov ecx, ; buffer
; ecx = (char *) buffermov [esp+4], "SGVsbG8K"
<sp> [....] [*"SGV....] |*****mov [esp], ecx
<sp> [*buffer] [*"SGV....] |*****call bd
; eip = *bd然后机器开始解释执行我们的程序逻辑:
push ebp<sp> [*bp@main] [return@main] [*buffer] [*"SGV....] |*****
mov ebp, esp
<sp><bp> [*bp@main] [return@main] [*buffer] [*"SGV....] |*****push ebx
<sp> [bx@main] <bp> [*bp@main] [return@main] [*buffer] [*"SGV....] |*****lea esp, [esp-(4*2 * 2)]
<sp> [........] [........] [bx@main] <bp> [*bp@main] [return@main] [*buffer] [*"SGV....] |*****==
call __x86_get_pc_thunk_bx
<sp> [return@bd] [........] [........] [bx@main] <bp> [*bp@main] [return@main] [*buffer] [*"SGV....]; eip = *__x86_get_pc_thunk_bx
mov ebx, dword [esp]
; ebx = (long) *<sp>(其实就是拿到位于 .text 段的 ip 指针,也就是
.text+bd+???,GCC 4.9 拿这个 bx (就是当前函数位于的 call __x86_get_pc_thunk_bx 时的 eip)指针去算 .rodata 段的静态只读数据地址)(我们要重新用汇编重写的时候必须也重写这种 ebx 偏移量,把对它们的使用替换成 .rodata 段实际的偏移地址,NASM 可以帮我们做这件事,直接
section .rodata 然后定义 byte/dword 静态数据指针就可以了)ret
<sp> [........] [........] [bx@main] <bp> [*bp@main] [return@main] [*buffer] [*"SGV....]; eip = *bd
; eax = *bd+5i
== 然后我们又回到了自己的程序
add ebx, 0x23fb
; 现在 ebx 指向了 .rodata (ds)段的某个地址,不过,本函数是不用; GCC(GNU Compiler Collection) 4.9 是相当老的编译器了,不要忘记现在 GCC 都出 8 了
mov eax, bd_arg2 (ebp+0xc)eax = my_arg2
mov bd_suba2(esp+0x4), eax
mov eax, bd_arg1 (ebp+0x8)eax = my_arg1
mov bd_suba1(esp), eax
<sp> [my_arg1|my_arg2] [........] [bx@main] <bp> [*bp@main] [return@main] [*buffer] [*"SGV....]🤔所以,我们为什么要多分配这么多无用的东西?浪费了一个双字的空间(虽然 mov subarg2 的时候可能溢出到别的存储单元)
call BD
; BD(my_arg1, my_arg2)🤔
lea esp, [esp+framesz]
[my_arg1|my_arg2] [........] <sp> [bx@main] <bp> [*bp@main] [return@main] [*buffer] [*"SGV....]一瞬返回
pop ebx
<sp> <bp> [*bp@main] [return@main] [*buffer] [*"SGV....]pop ebp<sp> [return@main] [*buffer] [*"SGV....]
ret一瞬重置代码指针返回 main+???
最后 main 收拾调用现场
== main+???
add esp, (2*4)
<sp> |*****对 bd 的调用就完成了(迫真)
duangsuse::Echo
lea esp, [esp - framesz] 有什么用呢? 🤔
注意:
1. 是
1.6. 我们要分配 4 个本地变量(4 * 4),当然也和我们自己调用子程序的部分有重叠
2. framesz 是 frame size 的意思,有时候你们看到的 sz 表示的 handle 们只是『碰巧』使用 size_t 机器字大小存储而已,所以叫 size,和这个无关
3. 我也不知道为什么 X86 的寄存器就会有 64 位了,因为这个是反汇编出来的程序又是 -m32 multlib 编译肯定有点奇怪啊
4. 我的机器很高级,支持 Debug Registers、FPU 还有 MMX、SSE、AVX 这些 SIMD 处理特性,可以快快的解码视频(迫真
6. 上面那些高等 Vectorize 处理特性,我们要分析的程序都不会用到(悲)
7. 这条指令执行前,esp 指向 0xb4f8,执行后,esp 指向 0xb4e4,下移了 20 个字节(合 5 个字)
8. 这啥 🐔 玩意,我也不知道它要干什么
9. 好吧,告诉你们,就是下移了 4 个字(4 * 4)而已,所谓 20 字节是我瞎 🐔 猜的
10. 所以现在看得懂汇编了吗?
1. 是
lea esp, [esp-framesz] 不是 mov esp, [esp-framesz]
1.5. 0x10 是 16 的意思,16 / 4 等于 41.6. 我们要分配 4 个本地变量(4 * 4),当然也和我们自己调用子程序的部分有重叠
2. framesz 是 frame size 的意思,有时候你们看到的 sz 表示的 handle 们只是『碰巧』使用 size_t 机器字大小存储而已,所以叫 size,和这个无关
3. 我也不知道为什么 X86 的寄存器就会有 64 位了,因为这个是反汇编出来的程序又是 -m32 multlib 编译肯定有点奇怪啊
4. 我的机器很高级,支持 Debug Registers、FPU 还有 MMX、SSE、AVX 这些 SIMD 处理特性,可以快快的解码视频(迫真
6. 上面那些高等 Vectorize 处理特性,我们要分析的程序都不会用到(悲)
7. 这条指令执行前,esp 指向 0xb4f8,执行后,esp 指向 0xb4e4,下移了 20 个字节(合 5 个字)
8. 这啥 🐔 玩意,我也不知道它要干什么
9. 好吧,告诉你们,就是下移了 4 个字(4 * 4)而已,所谓 20 字节是我瞎 🐔 猜的
10. 所以现在看得懂汇编了吗?
duangsuse::Echo
执行时是怎么样的呢? 🤔(当然这里可能不严谨,不过也够了,反正大家很多人连 CDEF 系统栈是怎么维护的都不知道,也算是科普一下) 我们的 caller 叫做 main,它执行如下代码以调用我们的子程序 bd: sub esp, (2*4) <sp> [....] [....] |***** mov ecx, ; buffer ; ecx = (char *) buffer mov [esp+4], "SGVsbG8K" <sp> [....] [*"SGV....] |***** mov [esp]…
🤔 实际上还是得重写 liba.so 真正自己的逻辑,不能直接反汇编然后啥都 OK 了...
duangsuse::Echo
lea esp, [esp - framesz] 有什么用呢? 🤔
This media is not supported in your browser
VIEW IN TELEGRAM
duangsuse::Echo
🐶 Sticker
(恍然大雾)我居然忘记给 NASM 加正确的 flag 了!
我没告诉 NASM,我是要给 i386 汇编!
难怪会出现机器字大小不兼容,frame 分配冲突错误(大寄存器 vs 小 frame local variable allocation = read/write 读取或覆盖无关变量)的问题
也就是说... 为什么 e** 寄存器都有 64 位?是因为我的机器是 x86_64 的,而且它自己的机器寄存器大小就有 128 位... 🙁
rax 是一个 qword,那 eax 自然有一个 dword... 🙊
真的是太 *** 了....
我没告诉 NASM,我是要给 i386 汇编!
难怪会出现机器字大小不兼容,frame 分配冲突错误(大寄存器 vs 小 frame local variable allocation = read/write 读取或覆盖无关变量)的问题
也就是说... 为什么 e** 寄存器都有 64 位?是因为我的机器是 x86_64 的,而且它自己的机器寄存器大小就有 128 位... 🙁
rax 是一个 qword,那 eax 自然有一个 dword... 🙊
真的是太 *** 了....
duangsuse::Echo
🤔 实际上还是得重写 liba.so 真正自己的逻辑,不能直接反汇编然后啥都 OK 了...
事实上:本来应该可以的,但是因为我根本没考虑过 *** 的问题,所以居然还有问题!
🤔 觉得调试符号里会保存关于本地变量偏移的信息,正在迫真查找...
duangsuse::Echo
duangsuse 一通莫名其妙的 local variable extract & reallocation 居然工作正常了,可喜可贺(又被当成编译器用的 duangsuse....)
说实在话,2014 年的 GCC 4.x 做的优化是有,但是它生成的代码非常模式化(比如函数调用基本就是个模板)
所以说反汇编再弄成汇编项目,虽然逆向工程都需要花时间但容易很多。
可是现在即使是基于 SSA 的 native code decompiler RetDec 反编译的结果参考价值都很低,几乎可以说等于没有,还不如 Radare 2 抽象执行自动分析呢
所以说反汇编再弄成汇编项目,虽然逆向工程都需要花时间但容易很多。
可是现在即使是基于 SSA 的 native code decompiler RetDec 反编译的结果参考价值都很低,几乎可以说等于没有,还不如 Radare 2 抽象执行自动分析呢
duangsuse::Echo
说实在话,2014 年的 GCC 4.x 做的优化是有,但是它生成的代码非常模式化(比如函数调用基本就是个模板) 所以说反汇编再弄成汇编项目,虽然逆向工程都需要花时间但容易很多。 可是现在即使是基于 SSA 的 native code decompiler RetDec 反编译的结果参考价值都很低,几乎可以说等于没有,还不如 Radare 2 抽象执行自动分析呢
RetDec 目前对一些简单编译优化的反编译结果参考价值低,从一个侧面劝谏大家要学习去看到汇编后面的东西,不能只会编译一个反编译器然后妄想像 Java 逆向一样,只需要解决混淆的问题就完了。
『手工』反编译需要有基本的编译原理基础,使用 SSA 的思路把树『收』起来也是个不错的想法
『手工』反编译需要有基本的编译原理基础,使用 SSA 的思路把树『收』起来也是个不错的想法
duangsuse::Echo
duangsuse 一通莫名其妙的 local variable extract & reallocation 居然工作正常了,可喜可贺(又被当成编译器用的 duangsuse....)
This media is not supported in your browser
VIEW IN TELEGRAM
其实最后还是我搞错了,两个十六进制数位可以表示一个字节(0-256,0x00-0xff),四个字节是一个字,所以 edb 里的寄存器实际上的确是一个字,不是我想的那样,x86_64 的 r** 也都是 64 位,不是 128 位
在之前我看来好像 ab cd 这四个应该是『一个字』(匹配 .... 这四个单单的数位模式),其实 ab 是一个字节、 cd 又是一个字节,加起来一个半字,远远没有一个字那么长
在之前我看来好像 ab cd 这四个应该是『一个字』(匹配 .... 这四个单单的数位模式),其实 ab 是一个字节、 cd 又是一个字节,加起来一个半字,远远没有一个字那么长
duangsuse::Echo
所以这个『64』位闹剧终于结束了 😵... 真的是相当无聊啊
This media is not supported in your browser
VIEW IN TELEGRAM