c语言的反编译问题
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了c语言的反编译问题相关的知识,希望对你有一定的参考价值。
手上有个EX4文件..
是基于C语言编写的..
听说有个ex42mq4软件可以把它转为MQ4文件..
有人知道么?
或是可以反编译源码出来的高手.
有么?
QQ:52039179
c言语写的 除非是特别简单例如 HELLO WOLRD 那样的代码
否则 你放弃把 参考技术B 反编译源码——不可能——因为你的变量名全被舍弃,在编译时变成地址代码了。本回答被提问者采纳 参考技术C 一般编译程序是不可以反编译到源程序的,
有一些写的程序听说可以基本上反编译出源码:java vb 参考技术D 用w32asm可以反编译成汇编语言,如果你汇编好的话就没问题.
了解对象到源代码的反编译
【中文标题】了解对象到源代码的反编译【英文标题】:Understanding the decompilation of an object to source code 【发布时间】:2020-09-20 03:42:54 【问题描述】:首先,我是一名学生,我对C、C++和汇编程序的知识还不是很全面,所以我非常努力地理解它。
我有一段来自 Intel x86-32 位处理器的汇编代码。
我的目标是将其转换为源代码。
0x80483dc <main>: push ebp
0x80483dd <main+1>: mov ebp,esp
0x80483df <main+3>: sub esp,0x10
0x80483e2 <main+6>: mov DWORD PTR [ebp-0x8],0x80484d0
0x80483e9 <main+13>: lea eax,[ebp-0x8]
0x80483ec <main+16>: mov DWORD PTR [ebp-0x4],eax
0x80483ef <main+19>: mov eax,DWORD PTR [ebp-0x4]
0x80483f2 <main+22>: mov edx,DWORD PTR [eax+0xc]
0x80483f5 <main+25>: mov eax,DWORD PTR [ebp-0x4]
0x80483f8 <main+28>: movzx eax,WORD PTR [eax+0x10]
0x80483fc <main+32>: cwde
0x80483fd <main+33>: add edx, eax
0x80483ff <main+35>: mov eax,DWORD PTR [ebp-0x4]
0x8048402 <main+38>: mov DWORD PTR [eax+0xc],edx
0x8048405 <main+41>: mov eax,DWORD PTR [ebp-0x4]
0x8048408 <main+44>: movzx eax,BYTE PTR [eax]
0x804840b <main+47>: cmp al,0x4f
0x804840d <main+49>: jne 0x8048419 <main+61>
0x804840f <main+51>: mov eax,DWORD PTR [ebp-0x4]
0x8048412 <main+54>: movzx eax,BYTE PTR [eax]
0x8048415 <main+57>: cmp al,0x4b
0x8048417 <main+59>: je 0x804842d <main+81>
0x8048419 <main+61>: mov eax,DWORD PTR [ebp-0x4]
0x804841c <main+64>: mov eax,DWORD PTR [eax+0xc]
0x804841f <main+67>: mov edx, eax
0x8048421 <main+69>: and edx,0xf0f0f0f
0x8048427 <main+75>: mov eax,DWORD PTR [ebp-0x4]
0x804842a <main+78>: mov DWORD PTR [eax+0x4],edx
0x804842d <main+81>: mov eax,0x0
0x8048432 <main+86>: leave
0x8048433 <main+87>: ret
这是我从代码中了解到的:
有4个变量:
a = [ebp-0x8] ebp
b = [ebp-0x4] eax
c = [eax + 0xc] edx
d = [eax + 0x10] eax
价值观:
0x4 = 4
0x8 = 8
0xc = 12
0x10 = 16
0x4b = 75
0x4f = 79
类型:
char (8 bits) = 1 BYTE
short (16 bits) = WORD
int (32 bit) = DWORD
long (32 bits) = DWORD
long long (32 bit) = DWORD
这是我能够创建的:
#include <stdio.h>
int main (void)
int a = 0x80484d0;
int b
short c;
int d;
c + b?
if (79 <= al)
instructions
else
instructions
return 0
但我被困住了。我也无法理解“cmp al ..”这个句子与什么相比,“al”是什么?
这些说明如何工作?
编辑1:
也就是说,正如你评论的那样,大会似乎是错误的,或者正如某些 cmets 所说,这太疯狂了!
代码和练习来自以下书籍:“逆向,逆向工程”第 140 页(3.8 建议练习)。我永远不会想到这是错误的,如果是这样,这显然让我难以学习......
所以不能逆向获取源代码,因为它不是一个好的汇编?也许我没有被压迫?可以优化吗?
编辑2:
嗨!
我确实问过,最后她说这应该是 c 代码:
inf foo(void)
char *string;//ebp-0x8
unsigned int *pointerstring//[ebp-0x4]
unsigned int *position;
*position = *(pointerstring+0xc);
unsigned char character;
character=(unsigned char) string[*position];
if ((character != 0x4)||(character != 0x4b))
*(position+0x4)=(unsigned int)(*position & 0x0f0f0f0f);
return(0);
这对你有任何意义吗?有人可以向我解释一下吗? 真的有人这样编程吗?
非常感谢!
【问题讨论】:
long long (32 bit) = DWORD
不正确。 C++ 标准要求 long long
为 64 位。 (嗯,不完全是,但它必须支持的最大值是它需要 64 位来存储它)
如果您需要询问al
是什么,那么您需要对处理器进行更深入的研究,然后才能理解反汇编或汇编列表。 al
寄存器是eax
寄存器的最低有效 8 位,ax
是 l.s. eax
的 16 位。 bl
、cl
、dl
、bx
、cx
和 dx
类似。 ah
也是 eax
的下 8 位,因此 ah
和 al
一起构成 ax
。
Here's a link to the documentation。查找标题为“基本程序执行寄存器”的部分
@PeterCordes 我不认为你在放屁。我认为那个大会有一些非常奇怪的地方。特别是在0x80483f2 <main+22>: mov edx,DWORD PTR [eax+0xc]
之后,在我看来,返回地址最终会出现在edx
中,考虑到随后的代码如何处理它,这似乎是不可取的。
除非章节是关于混淆代码的,否则我会写信给作者。代码中有一个微不足道的逻辑错误,而且这本书没有在 Google 上弹出(你给我们的名字是对的吗?)所以我倾向于相信这本书要么有一个关于控制流混淆的精彩章节,要么有是由不应该写的人写的。
【参考方案1】:
你的程序集完全疯了。这大致相当于C:
int main()
int i = 0x80484d0; // in ebp-8
int *p = &i; // in ebp-4
p[3] += (short)p[4]; // add argc to the return address(!)
if((char)*p != 0x4f || (char)*p != 0x4b) // always true because of || instead of &&
p[1] = p[3] & 0xf0f0f0f; // note that p[1] is p
return 0;
很明显,这是非常糟糕的代码,几乎肯定不会达到程序员的预期。
【讨论】:
0x80484d0
可能是 .rodata 部分中的地址,所以我在想char *arr[1] = "something" ;
。但是,是的,int *p = (int*)arr;
和 UB 无法访问数组边界之外。我没看剩下的有多疯狂。
我问了我的老师,他说是因为他没有优化……老实说,如果你知道的不明白,我怀疑我也能做到..
@conjim “未优化”意味着代码做了正确的事情,但比必要的慢。这段代码做错了。
感谢您提供的信息,我想在这种情况下,没有什么可以做的了......我想也许我没有做对,但似乎每个人都同意这是错误的代码。【参考方案2】:
x86 汇编语言有着悠久的传统,并且大部分都保持了兼容性。我们需要回到故事开始的 8086/8088 芯片。这些是 16 位处理器,这意味着它们的寄存器的字长为 16 位。通用寄存器被命名为 AX、BX、CX 和 DX。 8086 具有操作这些寄存器的高 8 位和低 8 位部分的指令,这些寄存器随后被命名为 AH、AL、BH、BL、CH、CL、DH 和 DL。 This Wikipedia page 描述了这个,请看一下。
这些寄存器的 32 位版本前面有一个E
:EAX、EBX、ECX 等。
您提到的特定指令,例如cmp al,0x4f
是将 AX 寄存器的低字节与 0x4f 进行比较。比较实际上与减法相同,但不保存结果,仅设置标志。
对于 8086 指令集,there is a nice reference here。您的程序是 32 位代码,因此您至少需要 80386 指令参考。
【讨论】:
【参考方案3】:您已经分析了变量,这是一个很好的起点。您应该尝试在开始时为它们添加类型注释,大小,当用作指针时(如b
),指向什么类型/大小的指针。
知道[ebp-4]
是b
,我可能会更新您的变量图表如下:
c = [b + 0xc]
d = [b + 0x10]
e = [b + 0], size = byte
要分析的另一件事是控制流。对于大多数指令,控制流是顺序的,但某些指令会故意改变它。从广义上讲,当 pc 向前移动时,它会跳过一些代码,而当 pc 向后移动时,它会重复一些它已经运行过的代码。跳过代码用于构造 if-then、if-then-else 和跳出循环的语句。后退用于继续循环。
某些指令称为条件分支,在某些动态条件为真时:向前(或向后)跳过,在为假时执行简单的顺序前进到下一条指令(有时称为条件分支失败)。
这里的控制序列:
...
0x8048405 <main+41>: mov eax,DWORD PTR [ebp-0x4] b
0x8048408 <main+44>: movzx eax,BYTE PTR [eax] b->e
0x804840b <main+47>: cmp al,0x4f b->e <=> 'O'
0x804840d <main+49>: jne 0x8048419 <main+61> b->e != 'O' skip to 61
** we know that the letter, a->e, must be 'O' here
0x804840f <main+51>: mov eax,DWORD PTR [ebp-0x4] b
0x8048412 <main+54>: movzx eax,BYTE PTR [eax] b->e
0x8048415 <main+57>: cmp al,0x4b b->e <=> 'K'
0x8048417 <main+59>: je 0x804842d <main+81> b->e == 'K' skip to 81
** we know that the letter, a->e must not be 'K' here if we fall thru the above je
** this line can be reached by taken branch jne or by fall thru je
0x8048419 <main+61>: mov eax,DWORD PTR [ebp-0x4] ******
...
控制流到达最后一行标记为我们知道字母不是“O”或者不是“K”。
jne
指令用于跳过另一个测试的构造是短路||
运算符。因此控制结构是:
if ( a->e != 'O' || a->e != 'K' )
then-part
由于这两个条件分支是函数中唯一的流控修改,所以if没有else部分,也没有循环或其他if。
这段代码似乎有一点问题。
如果值不是 'O',则 then 部分将从第一个测试中触发。但是,如果我们进行第二次测试,我们已经知道字母是 'O',所以测试 'K' 是愚蠢的,并且会是真的('O' 不是 'K')。
因此,这个 if-then 将始终触发。
要么效率非常低,要么存在一个错误,可能是(可能)字符串中的下一个字母应该针对“K”而不是完全相同的字母进行测试。
【讨论】:
[ebp-4]
是 b
- b
不是指针变量,持有地址 ebp-8
?因此,与[eax + 0xc]
的偏移是索引到函数自己的堆栈帧,mov edx, [eax + 0xc]
加载函数的返回地址。 (Joseph Sible 和我 discussed this in comments;这对我们来说看起来很疯狂。我想知道原始代码是否在像 char *arr[1] = "hello" ;
这样的本地数组的范围之外进行索引?)
我仍然很困惑......但非常感谢您提供的信息。有没有办法自动将目标代码转换为源代码,即使它远程相似......但不完全是?谢谢以上是关于c语言的反编译问题的主要内容,如果未能解决你的问题,请参考以下文章