RE在软件领域的应用j叫做代码逆向工程(Reverse Code Engineering)。
动静结合
文件类型,PE头,Import/Export API,内部字符串,是否运行时解压缩,数字证书等。
还有使用反汇编工具查看内部代码,预测功能。
使用调试器(debugger)。
注意程序版本是debug还是release。一般学习时使用release。
调试器中一般内置反汇编模块,将二进制代码转换为汇编。
汇编语言依赖于cpu。intel和arm具有不同的汇编指令
EP:windows可执行文件的代码入口点,依赖于CPU。
在main函数之前,有一些vc的启动函数(stub code)。
跳到push 14
开头的代码处,这一段是vc++启动函数,跟踪可以找到main函数。
右键-search for ...
可以查找注释、标签等数据。
options-disasm-show symbolic address
,可选择标签等数据是否显示。
4种方法:
ctrl + g
,gotomain函数距离EP很远,常用查找代码方法有4种:
右键-search for-all referenced text strings
右键-search for-all intermodular calls
右键-search for-name in all calls
api的名称是不是通过源代码摘取的,而是借助PE文件格式的IAT(import address table)结构。
ollydbg不能导出加壳可执行文件的api函数调用列表。
api实现于c:\Windows\systems32
文件夹的dll文件。ollydbg的view-memory
,快捷键alt+m
2种方法:
ctrl+e
可以修改。
ctrl+g
时记着加0x
cmd | key |
---|---|
restart | ctrl+f2 |
step into | f7 |
step over | f8 |
execution till return | ctrl+f9 |
set/reset BreakPoint | f2 |
run (till breakpoint) | f9 |
display BPs | alt+b |
comment | ; |
label | : |
view memory | alt+m |
execute till cursor | f4 |
edit | ctrl+e |
edit assembly code | space |
字节序(byte ordering)是多字节数据在内存中存储或网络传输时各字节的存储顺序,有两种:
byte
和数组类型,两者存储顺序都一样。
寄存器是cpu内部的存储区域。
basic\ program\ running\ register
\begin{cases}
\\common\ reg
\begin{cases}
eax,ebx,ecx,edx\\
ebp,esp\\
esi,edi
\end{cases}
\\segment reg
\begin{cases}
cs,ds,ss\\
es,fs,gs
\end{cases}
\\program\ status\ and\ control\ reg
\begin{cases}
eflags
\end{cases}
\\pointer reg
\begin{cases}
eip
\end{cases}
\end{cases}
ESP相关指令:push,pop,call,ret
ESI、EDI主要用于内存复制,相关指令:lods,stos,rep,movs
FS、GS和DS一样,都是数据段寄存器。
IA-32的保护模式中,段是一种内存保护技术,它把内存划分为多个段保护,还同分页技术(paging)将虚拟内存转换为物理内存。段内存记录在SDT(segment descriptor table),段寄存器持有sdt的索引。
调试中经常用到FS,它用来计算SEH,TEB,PEB等地址。
EFLAGS的3个与调试关系密切的标志位:ZF,OF,CF
可间接修改EIP的命令:jmp,jcc,call,ret
,也可以通过中断或异常来修改。
作用:
现在有些编译器带有Optimization
选项,编译简单函数不会生成栈帧,即内联(inline)。
ollydbg栈窗口右键,address-relative to EBP
,可以确认EBP的位置。
两种函数结束后的调用约定(calling convention):
ollydbg的debugging options一些选项,比如analysis-show ARGs...
vb专用引擎名为MSVBVM60.dll,也叫the thunder runtime engine。
vc++、vb常用间接调用法,不直接调用vb引擎的主函数ThunRTMain()
,而是通过中间地址的jmp
跳转到IAT的实际地址。
函数执行完毕后,不需要清理栈中的参数,那只会浪费cpu资源。