c++反汇编与逆向分析 小结

第一章  熟悉工作环境和相关工具
1.1 熟悉OllyDBG  操作技巧
1.2 反汇编静态分析工具
IDA(最专业的逆向工具)
    快捷键    功能

    Enter     跟进函数实现
   
Esc       返回跟进处
   
A         解释光标处的地址为一个字符串的首地址

    B        
十六进制数与二进制数转换
   
C         解释光标处的地址为一条指令

    D        
解释光标处的地址为数据,没按一次将会转换这个地址的数据长度
   
G         高速查找到相应的地址

    H        
十六进制数与十进制数转换
   
K         将数据解释为栈变量

    ;         加入?凝视

    M         解释为枚举成员

    N         又一次命名

    O        
解释地址为数据段偏移量
   
T         解释数据为一个结构体成员

    X        
转换视图到交叉參考模式
    Shift+F9  加入?结构体

认识各视图功能
    IDA
View-A:分析视图窗体,用于显示分析结果。
    Hex View-A:二进制视图窗体,打开文件的二进制信息。

    Exports: 分析文件里的导出函数信息窗体
    Imports:
分析文件里的导入函数信息窗体
    Names:  名称窗体,分析文档中用到的标题号名称。

    Functions: 分析文件里的函数信息窗体
   
Structures:加入?结构体信息窗体
    Enums: 加入?枚举信息窗体

SIG文件的制作步骤 1、从LIB文件里提取出OBJ文件 2、将每一个OBJ文件制作成PAT文件
3、多PAT文件联合编译SIG文件

SIG文件制作批处理文件的过程
md %l_objs
cd %l_objs
for /F %%i
in (‘link - lib /list %l.lib‘) do link -lib /extract:%%i %l.lib
for %%i in
(*.obj) do pcf %%i
sigmake -n"%l.lib" *.pat %l.sig
if exist %l.exc for %%i
in (%l.exc) do find /v ";" %%i >adc.exc
if exist %l.exc for %%i in
(%l.exc) do > abc.exc more +2 "%%i"
copy abc.exc %l.exc
del abc.exc

sigmake -n"%l.lib" *.pat %l.sig
copy %l.sig ..\%l.sig
cd ..
del %l_objs
/s /q
rd %l_objs

代码说明
通过 md%l_objs 创建文件夹,文件夹名称为參数1
通过 cd %l_objs 进入刚刚创建的文件夹
在当前文件夹下
循环取出 LIB 中的OBJ名称 并逐个生成相应的OBJ
循环将生成的OBJ文件通过PCF转换相应的PAT文件

将文件夹下的全部的PAT文件生成一个SIG文件
将生成的SIG文件复制到上级文件夹中
返回上级文件夹,删除创建的文件夹中的全部数据

将创建文件夹删除

1.3 反汇编引擎的工作原理
  Instruction Prefixes: 指令前缀
  
反复指令:REP、REPE\REPZ
   跨段指令:如 MOV DWORD PTR FS:[xxxx],0

   32位 16位 互换 如:MOV AX,WORD PTR DS:[EAX]   MOV EAX,DWORD PTR
DS:[BX+SI]
  Opcode: 指令操作码
  Mode R/M:操作数类型
  SIB:辅助
Mode R/M,计算地址偏移
  Displacement:辅助 Mode R/M, 计算地址偏移
 
Immediate:马上数

第二章 基本数据类型的表现形式
2.1 整数类型
    无符号整数 
有符号整数    差别就是最大位
2.2 浮点数类型
   
浮点数的编码方式  在内存中占4字节 最高位符号 剩余的31位中 左取8位指数 其余尾数
   
浮点寄存器的使用就是压栈/出栈的过程
    
比如
 float fFloat
=(float)argc;  //argc为命令行參数

fild dword ptr [ebp+8] ;将地址ebp+8处的整形数据转换浮点型,并入st(0)中,相应变量 argc

fst dword ptr [ebp-4] ;从st(0)中取出数据以浮点编码方式放入地址ebp-4中,相应变量fFloat

printf("%f",fFloat);

;这里对esp运行减8操作 是因为浮点数作为变參函数的參数时 须要转换为双精度浮点值
;这步操作时提前准备8字节的栈空间,以便于存放double
数据
sub esp,8

fstp dword ptr [esp] ;将st(0) 中的 数据传入esp中,并弹出st(0)

push offset string "%f"

call printf

add esp,0ch

argc =(int)fFloat;

fld dwrod ptr [ebp-4]  ;将地址 ebp-4处的数据以浮点数类型压入st(0)中

call _ftol ;调用函数_ftol 进行浮点类型转换

mov dword ptr [ebp+8],eax  ;转换后结果放入eax中,并转递到ebp+8地址处

类型转换函数 _ftol 的实现
push ebp
mov ebp,esp
add esp,0f4h

;浮点异常检查,CPU 与 FPU的同步工作
wait
fnstcw word ptr [ebp-2]
wait
mov ax,word
ptr [ebp-2]
or ah,0ch
mov word ptr [ebp-4],ax
fldcw word ptr
[ebp-4]

;从st(0)中取出8字节数据转换成整形并传入ebp-0ch中
;将st(0) 从栈中弹出
flstp dword ptr
[ebp-och]
fldcw word ptr [ebp-2]
;使用eax 保存长整形的低4位,用于返回
mov eax,dword
ptr [ebp-0ch]
;使用edx 保存长整形数据的高4字节,用于返回
mov edx,dword ptr [ebp-8]

;释放栈
leave
ret

2.3 字符和字符串
    字符串是由一系列依照一定的编码顺序线性排列的字符组成的

2.4 布尔类型
2.5 地址、指针和引用
  
地址是一个有32位二进制数字组成的值。指针是用于保存这个编号的一种变量类型。
  
指针的取内容操作分为两个步骤:先取出指针中保存的地址信息,然后针对这个地址进行去内容。
   两指针相加是没有意义的

   引用类型就是指针类型
2.6 常量
   
数据在程序执行前就已经存在,他们被编译到可执行文件里。
   
#define定义的常量名称,编译器对其进行编译时,会将代码中的宏名称替换成相应的信息。
    const
是为了添加?程序的健壮性而存在的
    #define 是一个真常量,而const
却是由编译器推断实现的常量,是一个假常量。

第三章  认识启动函数,找到用户入口

mian函数被调用前要先调用的函数 例如以下

GetVersion()  版本
_heap_init()  初始化堆空间
GetCommandLineA() 
获得命令行首地址
_crtGetEnviromentStringsA()  环境变量首地址
_setargv() 命令行參数首地址

_setenvp()  把得到的每条环境变量字符串的首地址存放在字符指针数组中
_cinit() 
全局数据和浮点寄存器的初始化

第四章 观察各种表达式的求值过程

加法 add    常量传播 和 常量折叠

      常量传播--将编译期间可计算出结果的变量转换成常量,这样就降低了变量的使用。

      常量折叠--全部的常量计算都将被计算结果取代。
   减法
sub 
比如:
 int nVarOne=argc;
012E13CE 
mov         eax,dword ptr
[argc] 
012E13D1 
mov         dword ptr
[nVarOne],eax 
  int nVarTwo=0;
012E13D4 
mov         dword ptr
[nVarTwo],0 
  scanf("%d",&nVarTwo);
012E13DB 
mov         esi,esp 

012E13DD  lea        
eax,[nVarTwo] 
012E13E0 
push        eax  
012E13E1 
push        offset string "%d"
(12E5750h) 
012E13E6 
call        dword ptr [__imp__scanf
(12E82BCh)] 
012E13EC 
add         esp,8 

012E13EF  cmp        
esi,esp 
012E13F1  call       
@ILT+325(__RTC_CheckEsp) (12E114Ah) 
  nVarOne=nVarOne-100;

012E13F6  mov         eax,dword ptr
[nVarOne] 
012E13F9 
sub         eax,64h 

012E13FC  mov         dword ptr
[nVarOne],eax

nVarOne=nVarOne+5-nVarTwo;
012E13FF 
mov         eax,dword ptr
[nVarOne] 
012E1402 
add         eax,5 

012E1405  sub         eax,dword ptr
[nVarTwo] 
012E1408 
mov         dword ptr [nVarOne],eax

printf("nVarOne = %d \r\n",nVarOne);
012E140B 
mov         esi,esp 

012E140D  mov         eax,dword ptr
[nVarOne] 
012E1410  push       
eax  
012E1411  push       
offset string "nVarOne = %d \r\n" (12E573Ch) 
012E1416 
call        dword ptr [__imp__printf
(12E82C4h)] 
012E141C 
add         esp,8

乘法 有符号 imul  和  无符号 mul 两种  样例直接编译
  除法 有符号
idiv  和  无符号 div 两种  样例直接编译

推断除法 总结 1 
  mov eax,MagicNumber
  imul …

  sar edx,…
  mov reg,edx
  shr reg,1fh
  add
edx,reg
  ;此后直接仅仅用edx的值,eax弃而不用

推断除法 总结 2
  mov eax,MagicNumber
 
;这里的reg表示通用寄存器,上例中为ecx,实际分析中还可能是其它寄存器
  mul reg
  sub
reg,edx
  shr reg,1
  add reg,edx
  shr reg,A
;这句也许没有
   ;此后直接仅仅用edx的值,eax弃而不用 
   

  
  推断除法 总结 3
  mov eax,MagicNumber
(大于7ffffffffh)
  imul reg
  add edx,reg
  sar edx,…

  mov reg,edx
  shr reg,1fh
  add edx,reg
 
;此后直接使用edx的值

推断除法 总结 4
  mov eax,MagicNumber (大于7ffffffffh)
  imul
reg
  sar edx,…
  mov reg,edx
  shr reg,1fh
 
add edx,reg
  ;此后直接使用edx的值

推断除法 总结 5
  mov eax,MagicNumber (大于7ffffffffh)
  imul
reg
  sub edx,reg
  sar edx,…
  mov reg,edx
 
shr reg,1fh
  add edx,reg
  ;此后直接使用edx的值

算数结果溢出 
  溢出是因为数据进位后超出数据的保存范围导致的
  进位--
无符号数超出存储范围叫做进位
  
  自增自减实例
 int nVarOne=argc;

0098138E  mov         eax,dword ptr
[argc] 
00981391 
mov         dword ptr
[nVarOne],eax 
  int nVarTwo=0;
00981394 
mov         dword ptr [nVarTwo],0

nVarTwo=5+(nVarOne++);
0098139B 
mov         eax,dword ptr
[nVarOne] 
0098139E 
add         eax,5 

009813A1  mov         dword ptr
[nVarTwo],eax 
009813A4 
mov         ecx,dword ptr
[nVarOne] 
009813A7 
add         ecx,1 

009813AA  mov         dword ptr
[nVarOne],ecx 
  nVarTwo=5+(++nVarOne);
009813AD 
mov         eax,dword ptr
[nVarOne] 
009813B0 
add         eax,1 

009813B3  mov         dword ptr
[nVarOne],eax 
009813B6 
mov         ecx,dword ptr
[nVarOne] 
009813B9 
add         ecx,5 

009813BC  mov         dword ptr
[nVarTwo],ecx

nVarOne=5+(nVarTwo++);
009813BF 
mov         eax,dword ptr
[nVarTwo] 
009813C2 
add         eax,5 

009813C5  mov         dword ptr
[nVarOne],eax 
009813C8 
mov         ecx,dword ptr
[nVarTwo] 
009813CB 
add         ecx,1 

009813CE  mov         dword ptr
[nVarTwo],ecx 
  nVarOne=5+(++nVarTwo);
009813D1 
mov         eax,dword ptr
[nVarTwo] 
009813D4 
add         eax,1 

009813D7  mov         dword ptr
[nVarTwo],eax 
009813DA 
mov         ecx,dword ptr
[nVarTwo] 
009813DD 
add         ecx,5 

009813E0  mov         dword ptr
[nVarOne],ecx

表达式短路--通过逻辑与运算和逻辑或运算使语句依据条件在运行时发生中断。

位运算
int BitOperation(int argc)
{
00BE1370 
push        ebp  
00BE1371 
mov         ebp,esp 

00BE1373  sub        
esp,0C0h 
00BE1379  push       
ebx  
00BE137A  push       
esi  
00BE137B  push       
edi  
00BE137C 
lea         edi,[ebp-0C0h] 

00BE1382  mov        
ecx,30h 
00BE1387 
mov         eax,0CCCCCCCCh 

00BE138C  rep stos    dword ptr es:[edi] 

  argc=argc<<3;
00BE138E 
mov         eax,dword ptr
[argc] 
00BE1391 
shl         eax,3 

00BE1394  mov         dword ptr
[argc],eax 
  argc=argc>>5;
00BE1397 
mov         eax,dword ptr
[argc] 
00BE139A 
sar         eax,5 

00BE139D  mov         dword ptr
[argc],eax 
  argc=argc|0xffff0000;
00BE13A0 
mov         eax,dword ptr
[argc] 
00BE13A3 
or         
eax,0FFFF0000h 
00BE13A8 
mov         dword ptr
[argc],eax 
  argc=argc&0x0000ffff;
00BE13AB 
mov         eax,dword ptr
[argc] 
00BE13AE 
and         eax,0FFFFh 

00BE13B3  mov         dword ptr
[argc],eax 
  argc=argc^0xffff0000;
00BE13B6 
mov         eax,dword ptr
[argc] 
00BE13B9 
xor         eax,0FFFF0000h 

00BE13BE  mov         dword ptr
[argc],eax 
  argc=~argc;
00BE13C1 
mov         eax,dword ptr
[argc] 
00BE13C4 
not         eax  

00BE13C6  mov         dword ptr
[argc],eax

return argc;
00BE13C9 
mov         eax,dword ptr
[argc] 
}
00BE13CC 
pop         edi  

00BE13CD  pop        
esi  
00BE13CE 
pop         ebx  

00BE13CF  mov        
esp,ebp 
00BE13D1 
pop         ebp  

00BE13D2  ret

reg==A?C:b+c  -->等效于以下

;遇到sub/neg/sbb 就表明是等值比較了
  sub reg,A
  neg reg
 
sbb reg,reg
  and reg,B
  add reg,C  若等值条件成立,其结果为C
否则b+c

比如
int BitOperation(int argc)
{
00DC1370 
push        ebp  
00DC1371 
mov         ebp,esp 

00DC1373  sub        
esp,0C0h 
00DC1379  push       
ebx  
00DC137A  push       
esi  
00DC137B  push       
edi  
00DC137C 
lea         edi,[ebp-0C0h] 

00DC1382  mov        
ecx,30h 
00DC1387 
mov         eax,0CCCCCCCCh 

00DC138C  rep stos    dword ptr es:[edi] 

  return argc ? 8 : 20;
00DC138E 
mov         eax,dword ptr
[argc] 
00DC1391 
neg         eax  

00DC1393  sbb        
eax,eax 
00DC1395 
and         eax,0FFFFFFF4h 

00DC1398  add        
eax,14h 
}
00DC139B 
pop         edi  

00DC139C  pop        
esi  
00DC139D 
pop         ebx  

00DC139E  mov        
esp,ebp 
00DC13A0 
pop         ebp  

00DC13A1 
ret

代码优化一般有四个方向:
  1 运行速度优化
  2 内存存储空间优化
  3
磁盘存储空间优化
  4 编译时间优化

第五章 流程控制语句的识别

if语句 
  总结:
  ;先运行各类影响标志位的指令
 
;其后是各种条件跳转指令
  jxx xxxxx

if...else...语句
  总结:
  ;先运行影响标志位的相关指令
  jxx
ELSE_BEGIN
  IF_BEGIN:
    ……
  IF_END:

    jmp  ELSE_END
  ELSE_BEGIN:

    ……
  ELSE_END;

用if构成的多分支流程
  总结:
  ;会影响标志位的指令
   jxx
ELSE_IF_BEGIN
  IF_BEGIN:
    ……
  IF_END:

    jmp END
  ELSE_IF_BEGIN:
  ;可影响标志位的指令

  jxx ELSE_BEGIN
  ……
  ELSE_IF_END:
   
jmp END
  ELSE_BEGIN:
  ……
  END:
  ……

Switch 的真相
  总结 1
  mov reg,mem
  ;影响标志位的指令

  jxx xxxx
  ;影响标志位的指令
  jxx xxx  
 
;影响标志位的指令
  jxx xxx
  jmp END
  ……
  jmp END

  ……
  jmp END
  ……
  END:
  ……

总结 2
  mov reg,mem
  ; 对变量进行运算,对齐case地址表的0下标,非必要

  ;上例中的eax 也可用其它寄存器替换,这里也能够是其它类型的运算
  lea eax,[reg+xxxx]
 
;影响标志位的指令,执行范围检查
  jxx DEFAULT_ADDR
  jmp dword ptr [eax*4+xxxx]
;

总结 3
  mov reg,mem
  sub reg,1
  mov
mem,reg
  ;影响标志位的指令
  jxx xxxx
  mov reg , [mem]

  ;eax不是必要用的,可是之后的数组查询用到的寄存器一定是此处使用的寄存器
  xor eax,eax
  mov
al,byte ptr [xxxx] [reg]
  jmp dword ptr [eax*4+xxxx]

do/while/for的比較
  
  do 总结
 
DO_BEGIN:
  .....
  ;影响标志位的指令
  jxx DO_BEGIN ;向上转

while 总结
  WHILE_BEGIN:
  ;影响标志位的指令
  jxx
WHILE_END
  .....
  jmp WHILE_BEGIN
  WHILE_END:

for 总结
  mov mem/reg,xxx
  jmp FOR_CMP
 
FOR_STEP:
  ;改动循环变量step
  mov reg,step
  add reg,xxxx ;
改动循环变量的计算过程
  mov setp,eax
  FOR_CMP:
  mov ecx,dword
ptr step
  ;推断循环变量和循环终止条件stepend的关系,满足条件则推出 循环
  cmp
ecx,setpend
  jxx FOR_END
  ……
  jmp FOR_STEP
 
FOR_END:

第六章 函数的工作原理

栈帧的形成和关闭
  栈在内存中是一块特殊的存储空间,它的存储原则是“先进后出”.
  esp 与
ebp  栈顶 与 栈底
  当 esp 小于 ebp时 就形成了栈帧,栈帧中能够寻址的数据有局部 函数返回地址 函数參数等

  vc环境下的调用约定有三种
  _cdecl: c/c++默认的调用方式,调用方平衡堆栈,不定參数的函数能够使用。

  _stdcall:被调用方平衡堆栈,不定參数的函数无法使用
 
_fastcall:寄存器方式传參,被调用方平衡堆栈,不定參数的函数无法使用。

使用ebp 或 esp 寻址  寄存器相对间接寻址方式
  
  函数的參数
通过栈结构进行传递。
 
  C/C++将不定长參数的函数定义为:
  至少要有一个參数,
 
全部不定长的參数类型传入时都是dword类型
  需在某一个參数中描写叙述參数总个数或将最后一个參数赋值为结尾标记

函数调用的一般工作流程
  1 參数传递 
   
通过栈或寄存器方式传递參数
  2 函数调用,将返回地址压栈
    使用 call
指令调用參数,并将返回地址压入栈中
  3 保存栈底
    使用栈空间保存调用方的栈底寄存器
ebp
  4 申请栈空间和保存寄存器环境
    
依据函数内部局部变量的大小抬高栈顶让出相应的栈空间
     而且将要改动的寄存器保存在栈中
 
5 函数实现代码
  6 还原环境
  7 平衡栈空间
    
平衡局部变量使用的栈空间
  8  ret 返回,结束函数调用
    
更新eip
  9  调整 esp,平衡栈顶
    此处为_cdecl特有的方式,用于
平衡參数占用的栈顶

两种编译选项下的函数识别
  debug 
  
push
reg/mem/imm
……
call reg/mem/imm
add esp,xxx

jmp FUN_ADDR
FUN_ADDR:
push ebp
……
mov eax,0cccccccch
rep stos
dword ptr [edi];
……
pop ebp
ret

Release

push reg/mem/imm
……
call reg/mem/imm
add esp,xxxx

;函数实现内没有将局部变量初始化为0cccccccch
;若在函数体内不存在内联汇编或异常处理等代码 则使用esp 寻址

c++反汇编与逆向分析 小结,布布扣,bubuko.com

时间: 2024-10-13 22:28:25

c++反汇编与逆向分析 小结的相关文章

《C++反汇编与逆向分析技术揭秘》--认识启动函数,找到用户入口

<C++反汇编与逆向分析>和<程序员的自我修养>都是以VC6的代码作为例子讲解的.这里是在vs2017下,CRT代码有些区别,但整体流程上都是初始化环境,设置参数,最后转到用户main函数. class COne { public: COne() { printf("COne \r\n"); } ~COne() { printf("~COne \r\n"); } }; COne g_One; int main() { printf("

《C++反汇编与逆向分析技术揭秘》之十——析构函数

局部对象 当对象所在作用域结束之后,销毁栈空间,此时析构函数被调用. 举例: 函数返回时自动调用析构函数: 堆对象 调用析构代理函数来处理析构函数: 为什么使用析构代理函数来调用析构函数?考虑到如果delete的对象是一个对象数组,可以使用析构代理函数依次析构所有的对象.举例: 调用了构造代理函数: vector deleting destructor函数中先对标志位进行判断: 如果没有跳转,表明delete的是一个数组,则会调用调用析构代理函数对对象进行逐一的析构.如果进行了跳转,则只进行一次

《C++反汇编与逆向分析技术揭秘》之十一——虚函数

虚函数的机制 当类中定义有虚函数时,编译器会将该类中所有虚函数的首地址保存在一张地址表中,这张表被称为虚函数地址表.编译器还会在类中添加一个虚表指针. 举例: CVirtual类的构造函数中没有进行任何操作,但是我们来看构造函数内部,还是有一个赋初值的操作: 这个地址指向的是一个数组: 这些数组中的内容就是虚函数的指针: 值得注意的是,如果没有虚指针的存在,那么CVirtual大小就是4字节.有了这个指针存在就是8字节. 本例子中,使用了一个空的构造函数,但是编译器自己擅自插入了代码,实现了对虚

《C++反汇编与逆向分析技术揭秘》--数据类型

  浮点数类型 IEEE标准从逻辑上采用一个三元组{S, E, M}来表示一个数N,它规定基数为2,符号位S用0和1分别表示正和负,尾数M用原码表示,阶码E用移码表示.根据浮点数的规格化方法,尾数域的最高有效位总是1,由此,该标准约定这一位不予存储,而是认为隐藏在小数点的左边,因此,尾数域所表示的值是1.M(实际存储的是M),这样可使尾数的表示范围比实际存储多一位.为了表示指数的正负,阶码E通常采用移码方式来表示,将数据的指数e 加上一个固定的偏移量后作为该数的阶码,这样做既可避免出现正负指数,

自制反汇编逆向分析工具 迭代第三版本

将一个函数的分支跳转逆向生成cpp文件,使逆向分析过程从分支跳转的分析中解放出来,工具首要的作用是应当解放生产力. 下面是效果图: 然后附上上面效果图对应的反汇编源代码和工具逆向生成的cpp文件. 有了这个逆向出来的文件,接下来的逆向工作有点像在做填空,但已经帮大忙. 不能上传附件,贴代码. 某比较大的函数的反汇编代码 QuartzCore`CA::Context::commit_transaction: -> <+0>: pushq %rbp <+1>: movq %rsp

自制反汇编逆向分析工具 迭代第五版本 (一)

这个版本添加了几个功能,分开几篇来写. 本篇是关于这样一个功能,显示选定的条件指令与其它条件分支的关系. 它们的关系分别在初版分支形态分布图,和第二版的汇编代码对应图同样展示. 红色表示被选中的目标 蓝色表示被选定的指令的执行位置之前,可能因为条件跳转而直接跳入到被选中的条件分支内(,忽略该条件判断). 绿色表示在被选中的条件分支内,因为其它条件跳转而直接离开目前分支的代码. 紫色表示在被选中的条件分支内,无条件跳转分支并且直接离开目前分支的代码. 浅紫色表示在被选中的条件分支内,无条件跳转分支

自制反汇编逆向分析工具 迭代第四版本

上一个版本,本工具支持的第一个逆向策略,(对反汇编的函数体内的分支控制结构逆向生成cpp代码,)一直都可以正常工作,直到遇上了一个函数.这个使我的逆向策略算法失效的函数,主要的特点是它含有众多无条件跳转指令(,都是在函数体内的跳转). 为什么无条件跳转指令会使得我的第一个逆向算法失效,因为这些无条件跳转指令让函数的执行流变得不易于线性理解. 在一个没有反汇编出来的函数汇编代码中,如果无条件跳转指令很少,特殊地连一条无条件跳转指令也没有时,将汇编代码的执行流当作行文阅读,总可以找到一个特例让所有条

病毒木马查杀第006篇:熊猫烧香之逆向分析(中)

一.前言 上一篇文章讲解了"熊猫烧香"病毒样本的反汇编代码入口处的分析,虽然尚未研究到病毒的核心部分,但其实我们后续的分析与之前的思想是一致的.而越到核心部分,可能会遇到越来越多的API函数,结合所调用函数的参数进行分析,反而有助于我们更容易地理解病毒的行为.应当将分析出的每一个CALL函数,改为我们能够理解的名字,这往往也有助于对后续程序的理解. 二.病毒功能分析 上一篇文章的最后,我留下了三个CALL没有分析,现在进入第一个CALL,即sub_408024的内部查看一下: 图1 s

病毒木马查杀第005篇:熊猫烧香之逆向分析(上)

一.前言 对病毒进行逆向分析,可以彻底弄清楚病毒的行为,从而采取更有效的针对手段.为了节省篇幅,在这里我不打算将"熊猫烧香"进行彻底的分析,只会讲解一些比较重要的部分,大家只要掌握了这些思想,那么就可以处理很多的恶意程序了.一般来说,对病毒的静态分析,我们采用的工具是IDA Pro,动态分析则采用OllyDbg.由于后者会使病毒实际运行起来,所以为了安全起见,最好在虚拟机中操作.另外,在实际分析过程中,我们可能还需要一些辅助工具,比如侦壳或脱壳程序等.为了简单起见,这次研究的"