当前位置:首页 » 编程软件 » 反编译obj文件

反编译obj文件

发布时间: 2024-09-07 21:03:16

‘壹’ 什么是编译

编译器

编译器是一种特殊的程序,它可以把以特定编程语言写成的程序变为机器可以运行的机器码。我们把一个程序写好,这时我们利用的环境是文本编辑器。这时我程序把程序称为源程序。在此以后程序员可以运行相应的编译器,通过指定需要编译的文件的名称就可以把相应的源文件(通过一个复杂的过程)转化为机器码了。

[编辑]编译器工作方法
首先编译器进行语法分析,也就是要把那些字符串分离出来。然后进行语义分析,就是把各个由语法分析分析出的语法单元的意义搞清楚。最后生成的是目标文件,我们也称为obj文件。再经过链接器的链接就可以生成最后的可执行代码了。有些时候我们需要把多个文件产生的目标文件进行链接,产生最后的代码。我们把一过程称为交叉链接。

一个现代编译器的主要工作流程如下:

* 源程序(source code)→预处理器(preprocessor)→编译器(compiler)→汇编程序(assembler)→目标程序(object code)→连接器(链接器,Linker)→可执行程序(executables)

工作原理

编译是从源代码(通常为高级语言)到能直接被计算机或虚拟机执行的目标代码(通常为低级语言或机器言)。然而,也存在从低级语言到高级语言的编译器,这类编译器中用来从由高级语言生成的低级语言代码重新生成高级语言代码的又被叫做反编译器。也有从一种高级语言生成另一种高级语言的编译器,或者生成一种需要进一步处理的的中间代码的编译器(又叫级联)。

典型的编译器输出是由包含入口点的名字和地址以及外部调用(到不在这个目标文件中的函数调用)的机器代码所组成的目标文件。一组目标文件,不必是同一编译器产生,但使用的编译器必需采用同样的输出格式,可以链接在一起并生成可以由用户直接执行的可执行程序。

编译器种类

编译器可以生成用来在与编译器本身所在的计算机和操作系统(平台)相同的环境下运行的目标代码,这种编译器又叫做“本地”编译器。另外,编译器也可以生成用来在其它平台上运行的目标代码,这种编译器又叫做交叉编译器。交叉编译器在生成新的硬件平台时非常有用。“源码到源码编译器”是指用一种高级语言作为输入,输出也是高级语言的编译器。例如: 自动并行化编译器经常采用一种高级语言作为输入,转换其中的代码,并用并行代码注释对它进行注释(如OpenMP)或者用语言构造进行注释(如FORTRAN的DOALL指令)。

预处理器(preprocessor)

作用是通过代入预定义等程序段将源程序补充完整。

编译器前端(frontend)

前端主要负责解析(parse)输入的源程序,由词法分析器和语法分析器协同工作。词法分析器负责把源程序中的‘单词’(Token)找出来,语法分析器把这些分散的单词按预先定义好的语法组装成有意义的表达式,语句 ,函数等等。 例如“a = b + c;”前端词法分析器看到的是“a, =, b , +, c;”,语法分析器按定义的语法,先把他们组装成表达式“b + c”,再组装成“a = b + c”的语句。 前端还负责语义(semantic checking)的检查,例如检测参与运算的变量是否是同一类型的,简单的错误处理。最终的结果常常是一个抽象的语法树(abstract syntax tree,或 AST),这样后端可以在此基础上进一步优化,处理。

编译器后端(backend)

编译器后端主要负责分析,优化中间代码(Intermediate representation)以及生成机器代码(Code Generation)。

一般说来所有的编译器分析,优化,变型都可以分成两大类: 函数内(intraproceral)还是函数之间(interproceral)进行。很明显,函数间的分析,优化更准确,但需要更长的时间来完成。

编译器分析(compiler analysis)的对象是前端生成并传递过来的中间代码,现代的优化型编译器(optimizing compiler)常常用好几种层次的中间代码来表示程序,高层的中间代码(high level IR)接近输入的源程序的格式,与输入语言相关(language dependent),包含更多的全局性的信息,和源程序的结构;中层的中间代码(middle level IR)与输入语言无关,低层的中间代码(Low level IR)与机器语言类似。 不同的分析,优化发生在最适合的那一层中间代码上。

常见的编译分析有函数调用树(call tree),控制流程图(Control flow graph),以及在此基础上的变量定义-使用,使用-定义链(define-use/use-define or u-d/d-u chain),变量别名分析(alias analysis),指针分析(pointer analysis),数据依赖分析(data dependence analysis)等等。

上述的程序分析结果是编译器优化(compiler optimization)和程序变形(compiler transformation)的前提条件。常见的优化和变新有:函数内嵌(inlining),无用代码删除(Dead code elimination),标准化循环结构(loop normalization),循环体展开(loop unrolling),循环体合并,分裂(loop fusion,loop fission),数组填充(array padding),等等。优化和变形的目的是减少代码的长度,提高内存(memory),缓存(cache)的使用率,减少读写磁盘,访问网络数据的频率。更高级的优化甚至可以把序列化的代码(serial code)变成并行运算,多线程的代码(parallelized,multi-threaded code)。

机器代码的生成是优化变型后的中间代码转换成机器指令的过程。现代编译器主要采用生成汇编代码(assembly code)的策略,而不直接生成二进制的目标代码(binary object code)。即使在代码生成阶段,高级编译器仍然要做很多分析,优化,变形的工作。例如如何分配寄存器(register allocatioin),如何选择合适的机器指令(instruction selection),如何合并几句代码成一句等等。

‘贰’ 怎样知道一个EXE文件是用什么语言编写的怎样写的

通过看它和什么库链接可以猜测出用过哪些语言。
比如 java 语言写的程序一般不会不与 Java 运行时的 DLL 链接(名字好像叫jre.dll),Objective-C 和 Swift 语言写的程序往往是和objc运行时链接的。
C语言链接的DLL包括Unix/BSD/Linux系统上的 libc、libxnet 等,和 Windows 上的 Kernel.dll 等。C++也是如此,但链接的包括有 libstdcxx,和 Windows 上的 mfc*.dll。
至于是怎样写的,就要通过反编译来看了。

‘叁’ java强制类型转换:int i = (int)obj转换过程是怎样的

因为有Integer这个包装类,

如图是使用javap -c xx.class命令查看的反编译代码,Obj 1 = 1;其实是Obj 1 = Integer.valueOf(1);obj转int其实是obj转Integer再调用intvalue()方法转换成int类型

‘肆’ 用C++编出的exe文件能否被还原成cpp代码

可以但是相当不现实。与汇编的精简不同,C语言的编译链接会把相当多冗余的算法带到Obj和Exe里去(一来为了兼容不同硬件环境把各种算法都考虑到,二来因为其效率确实远不如汇编)。一个几十KB的Exe可能反编译出一本字典那么多的源程序。如果你不嫌费事可以上网找C语言的decompile软件试试。

‘伍’ Release文件夹下的其他文件

这些文件有:调试符号.pdb, 这个不要给用户,否则用户利用这个很容易反编译你的软件. vc60.idb/vc70.idb VC使用,对用户没有什么价值
.obj 连接需要的对象文件.

这些文件都不必给用户,只需要EXE就行

‘陆’ 混淆的class文件怎么进行反编译

一般情况下Java应用的开发者为了保护代码不被别人抄袭,在生成class文件的时候都java文件进行了混淆,这种class文件用反编译工具得到的结果很难看懂,并且不能进行编译。
从研究的角度,浅析如何读懂这种反编译过来的文件。
例子一:赋值
反编译过来的代码如下:
Node node;
Node node1 = _$3.getChildNodes().item(0);
node1;
node1;
JVM INSTR swap ;
node;
getChildNodes();
0;
item();
getChildNodes();
0;
item();
getNodeValue();
String s;
s;
原始语句:
Node node;
Node node1 = currDocument.getChildNodes().item(0);
node = node1;
String s = node.getChildNodes().item(0).getChildNodes().item(0).getNodeValue();
注解:
JVM INSTR swap ; //赋值语句
练习:
String s1;
String s8 = node.getChildNodes().item(1).getChildNodes().item(0).getNodeValue();
s8;
s8;
JVM INSTR swap ;
s1;
10;
Integer.parseInt();
int i;
i;

例子二:不带参数创建对象
反编译过来的代码如下:
JVM INSTR new #244 ;
JVM INSTR p ;
JVM INSTR swap ;
CrossTable();
CrossTable crosstable;
crosstable;
原始语句:
CrossTable crosstable = new CrossTable();
注解:
练习:
JVM INSTR new #246 ;
JVM INSTR p ;
JVM INSTR swap ;
Database();
Object obj;
obj;
例子三:带参数创建对象
反编译过来的代码如下:
JVM INSTR new #262 ;
JVM INSTR p ;
JVM INSTR swap ;
String.valueOf(s2);
StringBuffer();
s.substring(j, i);
append();
s6;
append();
toString();
s2;

原始语句:
s2 = (new StringBuffer(String.valueOf(s2))).append(s.substring(j, i)).append(s6).toString();
注解:
此语句实际上是:s2 += s.substring(j, i) + s6;
练习:
例子四:for循环
反编译过来的代码如下:
int k = 0;
goto _L4
_L8:
...
k++;
_L4:
if(k < as.length) goto _L8; else goto _L7
原始语句:
for(int k=0;k < as.length;k++)
{
...
}
注解:
例子五:while循环
反编译过来的代码如下:
String s1 = "";
goto _L1
_L3:
JVM INSTR new #262 ;
JVM INSTR p ;
JVM INSTR swap ;
String.valueOf(s1);
StringBuffer();
_$2(resultset, s, l);
append();
toString();
s1;
_L1:
if(resultset.next()) goto _L3; else goto _L2
原始语句:
String s1 = "";
while(resultset.next())
{
s1 = s1 + resultSetToString(resultset, s, l);
}

‘柒’ 一个51单片机C程序,里面有一个bin的文件,这个bin文件应该包含了几个重要的函数;能用什么打开!

这个一般是打不开的,打开就等于是盗用人家的代码。

lib文件

意义:
lib有静态lib和动态lib之分。

使用:
lib文件通过编译才可以使用,编译分静态与动态之分。

静态:
静态lib将导出声明和实现都放在lib中。编译后所有代码都嵌入到宿主程序

动态:
动态lib相当于一个h文件,是对实现部分(.dll文件)的导出部分的声明。编译后只是将导出声明部分编译到宿主程序中,运行时候需要相应的dll文件支持

详细说明:
lib文件是不对外公开的,不能查看一个编译过后的文件
有几个选择:
1。如果你查看有同名的dll文件,可以通过vc自带的depends查看dll接口
2。通过msdn看你使用的该lib包含的函数名,来查找其对应的头文件,头文件里面有整个lib的函数声明(可能不全)
3。查看vc或者其他工具安装目录下的src目录,查看函数的代码
lib文件是二进制文件,所以要查看它的内容,只能反汇编。
用编程语言,打开lib文件的办法有三个:
1、在object/library moles使用全路径名;
2、把*.lib放在VC的Lib目录中
3、修改project setting的Link->Input中的Addtional library path,加入你的目录。
LIB文件是库文件(与DLL文件相类似),供其它程序调用的,直接打不开。
内容

一个lib文件是obj文件的集合。当然,其中还夹杂着其他一些辅助信息,目的是为了让编译器能够准确找到对应的obj文件。我们可以通过tlib.exe(在tc2.0下的根目录)来对lib文件进行操作,你可以把自己生成的obj文件通过tlib命令加入到一个lib文件中,也可以把lib文件内的obj文件进行删除操作,还可以把内部的obj文件给提取出来。明白了lib文件的大致结构以及对它的具体操作,在学习C语言的过程中,就会又多了一个切入点对C语言具体实现进行研究。
使用步骤

在command下,把当前目录设置为tlib.exe所在目录,然后输入tlib命令回车,此时显示的内容就是对tlib命令的详细解释,语法如下:
Syntax: TLIB libname [/C] [/E] commands, listfile
libname library file pathname
commands sequence of operations to be performed (optional)
listfile file name for listing file (optional)
A command is of the form: <symbol>molename, where <symbol> is:
+ add molename to the library
- remove molename from the library
* extract molename without removing it
-+ or +- replace molename in library
-* or *- extract molename and remove it
/C case-sensitive library
/E create extended dictionary
具体解释:
tlib libname [/C] [/E] commands, listfile
/C:大小写敏感标志。该选项不常用,此参数为可选项。
/E:建立扩展字典。建立扩展字典可以加速大的库文件的连接过程,此参数同样为可选项。
操作命令(可选项):
+ obj文件名 把指定obj文件添加到lib文件中
- obj文件名 把指定obj文件从lib文件中删除
* obj文件名 导出指定的obj文件(导出后对应的obj文件在lib文件内仍然存在)
-+ obj文件名 替换指定的obj文件(前提是在lib文件中存在与指定obj文件同名的obj)
-* obj文件名 导出指定的obj文件(导出后把对应的obj文件从lib文件内删除)
lib文件中obj文件列表(可选项)
此参数说明了命令运行后,生成的对应lib文件的列表文件名。它记录了当前lib文件内obj文件列表
与dll区别编辑
(1)lib是编译时需要的,dll是运行时需要的。
如果要完成源代码的编译,有lib就够了。
如果也使动态连接的程序运行起来,有dll就够了。
在开发和调试阶段,当然最好都有。
(2)一般的动态库程序有lib文件和dll文件。lib文件是必须在编译期就连接到应用程序中的,而dll文件是运行期才会被调用的。如果有dll文件,那么对应的lib文件一般是一些索引信息,具体的实现在dll文件中。如果只有lib文件,那么这个lib文件是静态编译出来的,索引和实现都在其中。静态编译的lib文件有好处:给用户安装时就不需要再挂动态库了。但也有缺点,就是导致应用程序比较大,而且失去了动态库的灵活性,在版本升级时,同时要发布新的应用程序才行。
(3)在动态库的情况下,有两个文件,一个是引入库(.LIB)文件,一个是DLL文件,引入库文件包含被DLL导出的函数的名称和位置,DLL包含实际的函数和数据,应用程序使用LIB文件链接到所需要使用的DLL文件,库中的函数和数据并不复制到可执行文件中,因此在应用程序的可执行文件中,存放的不是被调用的函数代码,而是DLL中所要调用的函数的内存地址,这样当一个或多个应用程序运行时再把程序代码和被调用的函数代码链接起来,从而节省了内存资源。从上面的说明可以看出,DLL文件必须随应用程序一起发行,否则应用程序将会产生错误。
加载方法编辑
直接加入

在VC中打开File View一页,选中工程名,单击鼠标右键,然后选中"Add Files to Project"菜单,在弹出的文件对话框中选中要加入DLL的LIB文件即可。
设置

打开工程的 Project Settings菜单,选中Link,然后在Object/library moles下的文本框中输入DLL的LIB文件。
程序代码

加入预编译指令#pragma comment (lib,"*.lib"),这种方法优点是可以利用条件预编译指令链接不同版本的LIB文件。因为,在Debug方式下,产生的LIB文件是Debug版本,如Regd.lib;在Release方式下,产生的LIB文件是Release版本,如Regr.lib。
当应用程序对DLL的LIB文件加载后,还需要把DLL对应的头文件(*.h)包含到其中,在这个头文件中给出了DLL中定义的函数原型,然后声明。
详解
节的概念编辑
Lib格式只有四种类型的节(Section),即First Sec,Second Sec,Longname Sec和Obj Sec;其中Second Sec与Longname Sec是可选节,很多Lib文件中都没有。而开头的Singature只是一个标识,它相当于COFF目标文件中的魔法数字。它是一个长度为8的字符串,值为“!<arch>\n”。
First Sec 顾名思义,就是第一个节。它包含了库中所有的符号名以及这些符号所在的目标文件在库中的位置(绝对偏移)。
Second Sec 就是第二节。它的内容和First Sec是相同的。不同的是,Second Sec是一个有序表,通过它来查找库中的符号比通过First Sec来查找要快很多。
Longname Sec 是长名称节。这一节是一个字符串表。它包含了所有长目标文件名。如果后面的Obj Sec中没有给出相应的目标文件名,我们就要到这一节中来查找。
Obj Sec 就是目标文件节。这些节中存储着不同的目标文件的原始数据。
在库文件中,每一节都有两个部分。一个部分是头,另一个部分才是该节的数据;数据紧跟在头的后面。头描述了该节数据的类型、长度等信息。这些头的格式都是相同的。其结构用C语言描述如下:
typedef struct {
char Name[16]; // 名称
char Time[12]; // 时间
char UserID[6]; // 用户ID
char GroupID[6]; // 组ID
char Mode[8]; // 模式
char Size[10]; // 长度
char EndOfHeader[2];// 结束符
} SectionHeader;
可以看到,头中的数据全都是字符串。用字符串的好处是可以提高格式的兼容性,因为在不同的机器上,数据的排列方式是不同的。有的机器是以Little-Endian方式工作,还有的是以Big-Endian方式工作,它们互不兼容(这两种方式的区别!?请看我的《COFF格式》一文,其中的文件头一节有说明)。用字符串就不会有这种问题(后面我们将会遇到)。但它也有不方便的地方,就是必须把字符串转换成数值,多了一个步骤。
在这个结构中,最常用的Name、Size以及EndOfHeader三个成员。Name就是节的名称啦!Size也很好理解,就是该节数据的长度。其内容为“`\n”(注意,这里没有打错,是两个字符“`”和“\n”)。怎么样?有点奇怪吧?为什么要有这个结束符?每一节的头长度一定,每节中的数据长度也知道。按顺序向下读不行吗?答案是:不行!因为每一节之间存在间隙!通常是一个字节或零个字节。如果是零个字节倒好,按顺序向下读是OK的。可是如果不为零的话,这样读就要错位了。要知道错位没有,只好用一个结束符来定位了。如果在读头的时候发现结束符不对,那就要一个字节一个字节地向下查找,直到找到结束符,才能算是对齐了。切记!切记!
当然,通过First Sec或Second Sec中给出的偏移来读数据就不存在这个问题。不会发生错位,放心读吧!
First Sec

第一节,通常就是Lib中的每一个小节。它的名称是“/”。其数据部分的结构如下:
typedef struct {
unsigned long SymbolNum; // 库中符号的数量
unsigned long SymbolOffset[n]; // 符号所在目标节的偏移
char StrTable[m]; // 符号名称字符串表
}FirstSec;
第一个成员SymbolNum是符号的数量。注意!它是以Big-Endian方式储存的(x86平台上的数据是以Little-Endian方式储存的。这里应该注意转换。后面给出的convert函数可以在Little-Endian格式与Big-Endian格式之间进行相互转换)。
第二个成员SymbolOffset是一个数组,它的长度n就是符号的数量,也就是SymbolNum。这个数组储存了每一个符号所在的目标节的偏移。我们可以方便地通过它来查找符号所在的目标文件。注意!它也是以Big-Endian格式储存的。
第三个成员StrTable是一个字符串表,它的长度m就是SectionHeader.Size的值减去(SymbolNum+1)*4。其结构很简单,就是一堆以‘\0’结尾的字符串(和COFF文件中的字符串表结构相同)。在有的系统中,它还可能是以“/\n”这两个字符结尾的字符串的集合。
很简单的一个结构,不过有两个成员的长度是不定的。怎么才能方便地从Lib中读出这些数据,留给大家自己想吧!下面我只给出一个进行Little-Endian与Big-Endian互转的函数。
inline void convert(void * p // 要转换的数据的指针
,size_tsize = 4 // 数据的长度,long为4,short为2
) {
char * buf=(char*)p;
char temp;
for ( size_t i=0;i<size/2;i++ ) {
temp=buf[i];
buf[i]=buf[size-i-1];
buf[size-i-1]=temp;
}
}
Second Sec

第二节
这一节与第一节很相似!它通常也就是Lib文件的第二个节。它的名字也是“/”(注意:文件中第一个叫“/”的节是第一节,第二个就是第二节)。不过它的结构与第一节有些不同,如下:
typedef struct {
unsigned long ObjNum; // Obj Sec的数量
unsigned long ObjOffset[x]; // 每一个Obj Sec的偏移
unsigned long SymbolNum; // 库中符号的数量
unsigned short SymbolIdx[n]; // 符号在ObjOffset表中的索引
char StrTable[m]; // 符号名称字符串表
}SecondSec;
第一个成员ObjNum是库中Obj Sec的数量。
第二个成员ObjOffset是一个偏移表,它记录了库中所有Obj Sec的偏移。这个表的记录数x就是ObjNum。
第三个成员SymbolNum与First Sec中的SymbolNum意义相同。
第四个成员SymbolIdx变成了一个索引,它记录了相应名称字符串在ObjOffset这个表中的位置,我们要通过两次索引才能找到我们所要符号的Obj Sec位置。它的项目数n为SymbolNum。但请注意,这个索引是unsigned short型,不再是unsigned long型。
第五个成员StrTable结构与First Sec中的一样。不过,它的长度m为SectionHeader.Size的值减去((ObjNum+1)*4+(SymbolNum+2)*2)。
值得注意的是,这里的所有数据都是Little-Endian格式的。千万不要弄错了!Longname Sec
这个小节就是一个字符串表,它的名称为“//”,其结构同FirstSec.StrTable。这里就不多说了。
Obj Sec
这一节中的数据就是COFF文件的原始数据,把它读出来存成文件,就是一个COFF文件。它的格式请参考《COFF格式》一文。
要指出的是它的命名方式有些特殊。如果Obj文件的名称少于16个字符,它就会被保存在SectionHeader的Name成员中,以‘/’字符结尾。如果无法保存在Name成员中,则Name成员的第一个字符就为‘/’,之后再跟上这个名称在Longname Sec中的偏移。
例如:
!<arch>\n
……
LongName Sec:
This_Is_Long_Name0001\0
This_Is_Long_Name0002\0
……
Obj Sec1:
Name[16]:“shortname/”
……
Obj Sec2:
Name[16]:“/0” // 这里使用了第一个长文件名This_Is_Long_Name0001
……
Obj Sec3:
Name[16]:“/22” // 这里使用了第二个长文件名This_Is_Long_Name0002

‘捌’ 程序脱壳是什么意思

壳的概念:
所谓“壳”就是专门压缩的工具。
这里的压缩并不是我们平时使用的RAR、ZIP这些工具的压缩,壳的压缩指的是针对exe、com、和dll等程序文件进行压缩,在程序中加入一段如同保护层的代码,使原程序文件代码失去本来面目,从而保护程序不被非法修改和反编译,这段如同保护层的代码,与自然界动植物的壳在功能上有很多相似的地方,所以我们就形象地称之为程序的壳。

壳的作用:
1.保护程序不被非法修改和反编译。
2.对程序专门进行压缩,以减小文件大小,方便传播和储存。

壳和压缩软件的压缩的区别是
压缩软件只能够压缩程序
而经过壳压缩后的exe、com和dll等程序文件可以跟正常的程序一样运行

下面来介绍一个检测壳的软件
PEID v0.92
这个软件可以检测出 450种壳
新版中增加病毒扫描功能,是目前各类查壳工具中,性能最强的。
另外还可识别出EXE文件是用什么语言编写的VC++、Delphi、VB或Delphi等。
支持文件夹批量扫描

我们用PEID对easymail.exe进行扫描
找到壳的类型了
UPX 0.89.6 - 1.02 / 1.05 - 1.24 -> Markus & Laszlo
说明是UPX的壳
下面进行

步骤2 脱壳
对一个加了壳的程序,去除其中无关的干扰信息和保护限制,把他的壳脱去,解除伪装,还原软件本来的面目。这个过程就叫做脱壳。
脱壳成功的标志
脱壳后的文件正常运行,功能没有损耗。
还有一般脱壳后的文件长度都会大于原文件的长度。
即使同一个文件,采用不同的脱壳软件进行脱壳,由于脱壳软件的机理不通,脱出来的文件大小也不尽相同。

关于脱壳有手动脱壳和自动脱壳
自动脱壳就是用专门的脱壳机脱 很简单 按几下就 OK了
手动脱壳相对自动脱壳 需要的技术含量微高 这里不多说了

UPX是一种很老而且强大的壳 不过它的脱壳机随处就能找到
UPX本身程序就可以通过
UPX 文件名 -d
解压缩 不过这些需要的 命令符中输入
优点方便快捷 缺点DOS界面
为了让大家省去麻烦的操作 就产生了一种叫 UPX SHELL的外壳软件

UPX SHELL v3.09
UPX 外壳程序!
目的让UPX的脱壳加壳傻瓜化

注:如果程序没有加壳 那么我们就可以省去第二步的脱壳了,直接对软件进行分析了。

脱完后 我们进行

步骤3
运行程序
尝试注册
获取注册相关信息

通过尝试注册 我们发现一个关键的字符串

“序列号输入错误”

步骤4
反汇编

反汇编一般用到的软件 都是 W32Dasm
W32dasm对于新手 易于上手 操作简单
W32Dasm有很多版本 这里我推荐使用 W32Dasm 无极版

我们现在反汇编WebEasyMail的程序文件easymail.exe

然后看看能不能找到刚才的字符串

步骤5
通过eXeScope这个软件来查看未能在w32dasm中正确显示的字符串信息

eXeScope v6.50
更改字体,更改菜单,更改对话框的排列,重写可执行文件的资源,包括(EXE,DLL,OCX)等。是方便强大的汉化工具,可以直接修改用 VC++ 及 DELPHI 编制的程序的资源,包括菜单、对话框、字符串表等
新版可以直接查看 加壳文件的资源

我们打开eXeScope
找到如下字串符

122,"序列号输入错误 "
123,"恭喜您成为WebEasyMail正式用户中的一员! "
124,注册成功
125,失败

重点是122

步骤6
再次返回 w32dasm

* Possible Reference to String Resource ID=00122: "?鲹e?"

但是双击后
提示说找不到这个字串符
不是没有 是因为 "?鲹e?"是乱码 w32dasm对于中文显示不是太好
毕竟不是国产软件

先把今天会用到的汇编基本指令跟大家解释一下

mov a,b ;把b的值赋给a,使a=b
call :调用子程序 ,子程序以ret结为
ret :返回主程序
je或jz :若相等则跳转
jne或jnz :若不相等则跳转
push xx:xx 压栈
pop xx:xx 出栈

栈,就是那些由编译器在需要的时候分配,在不需要的时候自动清楚的变量的存储区。里面的变量通常是局部变量、函数参数等。

我们搜索
Possible Reference to String Resource ID=00122
因为对E文支持很好
我们来到了

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00406F17(C) //跳转来自 406F17
|

* Possible Reference to String Resource ID=00125: "1%"
|
:004070DD 6A7D push 0000007D
:004070DF 8D4C2410 lea ecx, dword ptr [esp+10]
:004070E3 E8F75A1200 call 0052CBDF

* Possible Reference to String Resource ID=00122: "?鲹e?"
|
:004070E8 6A7A push 0000007A
:004070EA 8D4C2408 lea ecx, dword ptr [esp+08]
:004070EE E8EC5A1200 call 0052CBDF

我们来到

:00406F01 8B876C080000 mov eax, dword ptr [edi+0000086C]这里是对
:00406F07 8B4C2408 mov ecx, dword ptr [esp+08]
:00406F0B 50 push eax//这两个eax和ecx入栈就比较让我们怀疑了
:00406F0C 51 push ecx//产生注册码
:00406F0D E8AE381100 call 0051A7C0//这CALL里对注册位应该会有设置
:00406F12 83C40C add esp, 0000000C
:00406F15 85C0 test eax, eax// 检测注册位
:00406F17 0F85C0010000 jne 004070DD //不存在注册位 就会跳到4070DD就会出现那个错误的字串符了

我们记住406F01这个地址

接着进行下一步

步骤7
这一步我们进行的是调试

用到的软件是ollydbg

好了我们找到了 注册码0012AF04 00FD4A10 ASCII ""

但是这个并不是我们的主要目的

我们还要做出属于自己的注册机

相信这个是很多人梦寐以求的事情

步骤8
制作注册机

注册机我们需要的是一个KEYMAKE的软件
因为2.0是演示版而且停止更新了
所以我们用1.73版

做一个内存注册机 需要下面几个资料

中断地址:406F0C
中断次数:1
第一字节:51
指令长度:1

好了 一个完美的注册机 就产生了
还不赶快发给你的朋友 炫耀一下
保证让他迷糊死 佩服得你要死
其实最后还有几个步骤
就是撰写破文
不过大家都是新手 这个步骤 就去了吧

不知不觉说了这么多废话 希望能对大家有些作用
如果有什么不懂 不理解的事情 请联系我 或者到论坛发贴
QQ:9595859
MSN:[email protected]
今天的课程就到这里 大家赶快去动手实践吧~!

--------------------------------------------------------------------------------

-- 作者:admin
-- 发布时间:2005-10-11 11:13:00

-- 实战查壳脱壳制作破解注册机最详细的教程

大家好,我是kcarhc
今天8月1日了 刚从医院回来 正好凌晨
这期的课程做晚了 这里给大家道个歉
8月1日 如果我没记错
是建军节
既然是建军节 也要象征性的弄些东西来
为了建军节 这期我选择打击黑暗势力--黑社会

那么今天的主题就是
-----------
迎接建军节,铲除黑社会
-----------
首先介绍软件

黑社会2.0
[功能简介]:
1 五大必备功能
远程屏幕; 完全控制; 文件传送; Telnet; 远程关机
2 提供IP反弹定位功能
可以通过静态IP动态域名,网页文件的方式反弹通知IP.
3 集成vidc客户端
内网的朋友想用自动上线功能,可以实现了
4 本软件集成了常用攻击工具(如OpenTelnet OpenTftp等)
通过IPC拷贝,而且带有标准的拷贝进度,全球首次面世;
opentelnet就不介绍了,相信大家都知道;
opentftp为本软件独创,可以远程开启tftp服务;
5 本软件集成的极速端口扫描器(扫描速度世界领先)
最开始我用的扫描器是大名鼎鼎的SuperScan3.0,感觉速度很慢;
后来改用SSPort1.0 扫描速度有了明显的提高.
经过速度对比,本软件扫描速度比SSPort快 1/3 ,是SuperScan的N倍!!!
我的机器是 赛扬700+256M内存,一般扫描速度为180台/秒;
一些号称可以达到1000台/秒的扫描器在本机上试验只有120台/秒.
--------------------
准备工作:

安装黑社会
--------------------
步骤一 查壳

Peid v0.92
ASPack 2.12 -> Alexey Solodovnikov、
--------------------
步骤二 脱壳

手动脱壳

快速脱掉ASPACK所有版本的方法

的OEP关键点在下面

0048D3AF 61 POPAD
0048D3B0 75 08 JNZ SHORT 黑社会.0048D3BA
0048D3B2 B8 01000000 MOV EAX,1
0048D3B7 C2 0C00 RETN 0C//402c4a
0048D3BA 68 00000000 PUSH 0

402ca4就是我们要找的OEP

自动脱壳

AspackDie v1.41

这是一个小小的 PE 文件解压缩器 (EXE, DLL, ...) 她可以解压缩
自 Aspack 2000 以后的任何 Aspack 版本. 包括:

- Aspack 2000
- Aspack 2001
- Aspack 2.1
- Aspack 2.11
- Aspack 2.11c/d
- Aspack 2.12
- Aspack 2.12a/b
- 一些未知的版本

-------------------
步骤三 试运行程序 发现突破点

看到关键字符串
“注册码错误!”
-------------------
步骤四 W32DASM 寻找突破点

用w32dasm载入已经脱壳的程序
字符串察看
未发现 字符串 而是发现一堆乱码
大家于是一定想到了第一节的办法

用EXESCOPE
-------------------
步骤四 察找 字符串

打开eXeScope 并载入 但是发现 都没有字符串
这项
为啥呢?大家一定会疑问
一般用eXeScope查不到
我们将开始
-------------------
步骤五 查询软件的编译类型

Peid v0.92
Microsoft Visual Basic 5.0 / 6.0
--------------------
步骤六 采用GetVBRes v0.51 对付VB程序

GetVBRes v0.51 一个非常好的VB汉化工具

对于VB程序 我们用专门汉化用的GetVBRes v0.51来对付它
也许有人不理解 为啥用汉化工具呢
其实eXeScope也属于汉化工具
GetVBRes载入黑社会
发现没有乱码了
看到的全是完整的字符
我们找到了
注册码错误!
这个字符串
接着为了能搞到程序关键点地址
我们把“注册码错误!”
改成111111
为啥改成111111因为111111111
保存修改
---------------------
步骤六 用W32Dasm载入修改后的文件
发现字符串中有111111
那个就是我们修改的 原来是“注册码错误!”

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004792EF(C)
|
:00479474 B904000280 mov ecx, 80020004
:00479479 B80A000000 mov eax, 0000000A
:0047947E 894D9C mov dword ptr [ebp-64], ecx
:00479481 894DAC mov dword ptr [ebp-54], ecx
:00479484 894DBC mov dword ptr [ebp-44], ecx
:00479487 8D5584 lea edx, dword ptr [ebp-7C]
:0047948A 8D4DC4 lea ecx, dword ptr [ebp-3C]
:0047948D 894594 mov dword ptr [ebp-6C], eax
:00479490 8945A4 mov dword ptr [ebp-5C], eax
:00479493 8945B4 mov dword ptr [ebp-4C], eax

* Possible StringData Ref from Code Obj ->"1111111" //刚才我们看到的注册吗错误的哦
|
:00479496 C7458C98194100 mov [ebp-74], 00411998
:0047949D C7458408000000 mov [ebp-7C], 00000008

发现跳转来自到4792EF
安照习惯 我们来到4792EF后 接着向前看
看到一个跳到这里的那个地址
这里是40928C

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00479278(C)
|
:0047928C 8B55E4 mov edx, dword ptr [ebp-1C]

* Reference T MSVBVM60.__vbaStrMove, Ord:0000h
|
:0047928F 8B3578124000 mov esi, dword ptr [00401278]
:00479295 8D4DE0 lea ecx, dword ptr [ebp-20]
:00479298 895DE4 mov dword ptr [ebp-1C], ebx
:0047929B FFD6 call esi
:0047929D 8B4DE8 mov ecx, dword ptr [ebp-18]
:004792A0 6A01 push 00000001
:004792A2 8D55E0 lea edx, dword ptr [ebp-20]
:004792A5 51 push ecx
:004792A6 52 push edx
:004792A7 E8440F0000 call 0047A1F0
:004792AC 8BD0 mov edx, eax
:004792AE 8D4DDC lea ecx, dword ptr [ebp-24]
:004792B1 FFD6 call esi
:004792B3 50 push eax
:004792B4 53 push ebx

* Reference T MSVBVM60.__vbaInStr, Ord:0000h
|
:004792B5 FF15E8114000 Call dword ptr [004011E8]
:004792BB 8BF0 mov esi, eax
:004792BD 8D45E8 lea eax, dword ptr [ebp-18]
:004792C0 F7DE neg esi
:004792C2 8D4DDC lea ecx, dword ptr [ebp-24]
:004792C5 50 push eax
:004792C6 1BF6 sbb esi, esi
:004792C8 8D55E0 lea edx, dword ptr [ebp-20]
:004792CB 51 push ecx
:004792CC 52 push edx
:004792CD F7DE neg esi
:004792CF 6A03 push 00000003
:004792D1 F7DE neg esi

* Reference T MSVBVM60.__vbaFreeStrList, Ord:0000h
|
:004792D3 FF150C124000 Call dword ptr [0040120C]
:004792D9 8D45D4 lea eax, dword ptr [ebp-2C]
:004792DC 8D4DD8 lea ecx, dword ptr [ebp-28]
:004792DF 50 push eax
:004792E0 51 push ecx
:004792E1 6A02 push 00000002

* Reference T MSVBVM60.__vbaFreeObjList, Ord:0000h
|
:004792E3 FF1548104000 Call dword ptr [00401048]
:004792E9 83C41C add esp, 0000001C
:004792EC 663BF3 cmp si, bx
:004792EF 0F847F010000 je 00479474

我们在
004792AC看到下面这些
EAX=0015A47C, (UNICODE "")
EDX=00000000

怀疑EAX为的

为注册码
------------------
步骤七 用不确定正确的注册 尝试注册



这个注册后
我们发现 注册成功
------------------
步骤八 制做注册机

Keymake v1.73

中断地址:4792AC
中断次数:1
第一字节:8B
指令长度:2
------------------
步骤九 发布注册机

找一个网站比如黑基或者你的朋友之间
------------------
步骤十 休息

黑社会终于干掉了
现在去找你的男朋友或者女朋友
老公或者老婆
找个地方聊聊天 放松放松
告诉他们 你刚刚把黑社会 摆平了
一定很有趣的
------------------
课程结束
------------------
有事情大家可以去论坛
不过你如果性子急
或者嫌我回复的速度慢
我建议你直接联系我
只要我在 基本可以马上给你解答
不在可以留言
我的两个联系方式
QQ:9595859
MSN:[email protected]
最后 说一个事
我的女朋友最近生病了
所以才导致这期的课程 这么晚才做出来
希望大家能理解我
我还希望大家能祝福她早日康复
不然的话
你们见到我的日子可能会少了
甚至可能会消失在你们眼前
好了不说了 今天就是到此OVER吧
---------- kcarhc
2004年8月1日 凌晨 沈阳

--------------------------------------------------------------------------------

-- 作者:admin
-- 发布时间:2005-10-11 16:42:00

-- 使用OllyDbg快速脱壳

作者:KU-凌
目标:采用ASPACK、UPX加壳的NOTEPAD.EXE
工具:OllyDbg 1.09英文版、DUMP插件、PEditor
系统:Win98SE
关键词: 脱壳、OllyDbg、OD、DUMP、PUSHAD、POPAD

预备知识
大多数壳都有一个共同的特点。在壳准备开始解压时都要执行PUSHAD,当壳解压
完时都要调用POPAD。到底PUSHAD和POPAD是什么干什么用的呢?其实PUSHAD是用来将
所有普通寄存器顺序进栈的指令,POPAD是所有普通寄存器顺序出栈指令。POPAD的出
栈顺序和PUSHAD相反。壳为了保护寄存器,便在解压前将所有寄存器进栈保护起来,
当解压完成后又将寄存器出栈,恢复其原貌,并将IP设置为原程序的OEP。这样我们就可以通过这个特点快速脱掉多种软件的壳。

ASPACK篇
先用ASPACK将NOTEPAD.EXE加壳。用OllyDbg(以下简称OD)载入。看见光标停在
壳的入口处。
0040D001 >60PUSHAD ;壳的入口。准备开始解压,保护寄存器
0040D002E8 03000000CALLNOTEPAD.0040D00A
……
我们不管它,直接向下翻页找POPAD指令。在40D3AF处找到POPAD
……
0040D3AF61POPAD ;解压完成,恢复寄存器
0040D3B075 08JNZSHORT NOTEPAD.0040D3BA
0040D3B2B8 01000000MOVEAX, 1
0040D3B7C2 0C00RETN0C
0040D3BA68 CC104000PUSHNOTEPAD.004010CC ;返回到原程序OEP处
0040D3BFC3RETN
……
选定40D3AF这一行,F4运行到此处。在这里说明壳已经完成解压工作。并且返回到原
程序的入口处。F8单步到4010CC,这里便是原程序的OEP。用DUMP插件直接DUMP出来就可以了(在DUMP时注意将入口点改为10CC,即4010CC-400000=10CC,400000是映象基地址)。文件大小是77059字节,用PEditor重建PE头便可以了。未压缩的文件大小是53248字节,脱壳后的文件大小是60930字节。

UPX篇
用UPX将NOTEPAD.EXE加壳,然后用OD载入。停在PUSHAD处,用脱ASPACK同样的方
法,向下翻页找POPAD。
……
0040E9FE61POPAD
0040E9FF- E9 C826FFFFJMPNOTEPAD.004010CC
……
下面的JMP就是跳转到程序的OEP处。F4到40E9FF处,F8单步一下,来到OEP处,DUMP出来。DUMP文件的大小是65536字节,直接就可以运行。为了完美,用PEditor重建PE头。那么脱壳后的文件大小是60293字节。

后记
用上面说的方法,很多种壳都可以快速的手动脱掉。如果你没有OD的DUMP插件,
可以到新论坛的下载区找。如果实在没有,也可以直接停在OEP处用PEDump来DUMP。很久没有写东西了。这一篇是写给初学者练手的。其实壳也是软件,再怎么复杂都有可能被脱下来。祝你好运。
另外,转载时请保持本文的完整。

--------------------------------------------------------------------------------

-- 作者:admin
-- 发布时间:2005-10-11 17:10:00

-- 用Ollydbg手脱EncryptPE V1.2003.5.18加壳的DLL

有兄弟让看看EncryptPE加壳的DLL,我说新版的就不行了,搞不定的。后来看是EncryptPE V1.2003.5.18旧版加壳的,应该用的是老王老师发布的免费版。呵呵,所以脱了一下,顺便记录过程。
大家可以自己用EncryptPE V1.2003.5.18免费版加个EdrLib.dll看看。

—————————————————————————————————
一、避开IAT加密

设置Ollydbg忽略所有的异常选项。用IsDebug 1.4插件去掉Ollydbg的调试器标志。
添加“同时忽略0EEDFADE、C0000008、009B25C、00953D74”异常。

代码:--------------------------------------------------------------------------------
00877000 60 pushad//进入OD后停在这
00877001 9C pushfd
00877002 64:FF35 00000000 push dword ptr fs:[0]
00877009 E8 79010000 call EdrLib.00877187
--------------------------------------------------------------------------------

下断:BP IsDebuggerPresent 断下后取消断点
现在我们Ctrl+G:711A0000
为何用这个地址?因为V12003518.EPE是相同的。呵呵,钻了个旧版的空子。

其实可以再BP GetProcAddress,根据返回地址来判断。如果返回地址是711XXXXX,说明这是V12003518.EPE的调用,就可以取消断点Ctrl+F9返回了。具体情况以堆栈的返回地址为准。

现在Ctrl+S 在“整个区段”搜索命令序列:

代码:--------------------------------------------------------------------------------
mov eax,edi
mov edx,dword ptr ss:[ebp-8]
mov dword ptr ds:[eax],edx
xor eax,eax
--------------------------------------------------------------------------------

找到在711A339F处,我们在711A339F处下个 硬件执行 断点。
现在我们关闭Ollydbg,重新载入这个dll,直接Shift+F9运行,中断在711A339F处

代码:--------------------------------------------------------------------------------
711A339F 8BC7 mov eax,edi
711A33A1 8B55 F8 mov edx,dword ptr ss:[ebp-8]
//改为: mov edx,dword ptr ss:[ebp-4] ★ 正确函数写入
711A33A4 8910 mov dword ptr ds:[eax],edx
711A33A6 33C0 xor eax,eax
711A33A8 5A pop edx
711A33A9 59 pop ecx
711A33AA 59 pop ecx
711A33AB 64:8910 mov dword ptr fs:[eax],edx
711A33AE EB 0A jmp short V1200351.711A33BA
--------------------------------------------------------------------------------

把711A33A1处修改好之后,取消以前下的711A339F处的断点。
再Ctrl+S搜索命令序列:

代码:--------------------------------------------------------------------------------
add ebx,4
mov eax,dword ptr ss:[ebp-4C]
add eax,4
--------------------------------------------------------------------------------

找到在711A43C2处,我们在下面xor eax,eax的711A4401下断。Shift+F9运行

代码:--------------------------------------------------------------------------------
711A43C2 83C3 04 add ebx,4
711A43C5 8B45 B4 mov eax,dword ptr ss:[ebp-4C]
711A43C8 83C0 04 add eax,4
711A43CB 8945 B4 mov dword ptr ss:[ebp-4C],eax
711A43CE 8B03 mov eax,dword ptr ds:[ebx]
711A43D0 85C0 test eax,eax
711A43D2 0F87 39FDFFFF ja V1200351.711A4111
711A43D8 A1 74C71B71 mov eax,dword ptr ds:[711BC774]
711A43DD 8038 00 cmp byte ptr ds:[eax],0
711A43E0 75 1F jnz short V1200351.711A4401
711A43E2 8B45 C4 mov eax,dword ptr ss:[ebp-3C]
711A43E5 83C0 14 add eax,14
711A43E8 8945 C4 mov dword ptr ss:[ebp-3C],eax
711A43EB 8B45 C4 mov eax,dword ptr ss:[ebp-3C]
711A43EE 8378 0C 00 cmp dword ptr ds:[eax+C],0
711A43F2 76 0D jbe short V1200351.711A4401
711A43F4 8B45 C4 mov eax,dword ptr ss:[ebp-3C]
711A43F7 8378 10 00 cmp dword ptr ds:[eax+10],0
711A43FB 0F87 38FCFFFF ja V1200351.711A4039//循环处理IAT
711A4401 33C0 xor eax,eax//此处下断! ★
--------------------------------------------------------------------------------

当我们中断在711A4401处时IAT已经处理完毕,此时就可以用ImportREC得到正确的输入表了。
因为EncryptPE后面有自校验,所以我们返回711A33A1处,点右键->撤销选择,恢复原来的代码。

—————————————————————————————————
二、得到重定位表信息、获得OEP

Ctrl+S 在“整个区段”搜索命令序列:

热点内容
跳转页源码 发布:2024-09-17 03:13:05 浏览:543
html文件上传表单 发布:2024-09-17 03:08:02 浏览:784
聊天软件编程 发布:2024-09-17 03:00:07 浏览:726
linuxoracle安装路径 发布:2024-09-17 01:57:29 浏览:688
两个安卓手机照片怎么同步 发布:2024-09-17 01:51:53 浏览:207
cf编译后没有黑框跳出来 发布:2024-09-17 01:46:54 浏览:249
安卓怎么禁用应用读取列表 发布:2024-09-17 01:46:45 浏览:524
win10设密码在哪里 发布:2024-09-17 01:33:32 浏览:662
情逢敌手迅雷下载ftp 发布:2024-09-17 01:32:35 浏览:337
安卓如何让软件按照步骤自动运行 发布:2024-09-17 01:28:27 浏览:197