《有趣的二进制:软件安全与逆向分析》读书笔记:通过逆向工程学习如何读懂二进制代码
Posted 思源湖的鱼
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了《有趣的二进制:软件安全与逆向分析》读书笔记:通过逆向工程学习如何读懂二进制代码相关的知识,希望对你有一定的参考价值。
目录
前言
上一篇学完内网之后,打算学习一些逆向相关知识
本篇开始阅读学习《有趣的二进制:软件安全与逆向分析》,本章是通过逆向工程学习如何读懂二进制代码,主要是体验软件分析、静态分析和动态分析(可以理解为怕劝退读者)
作者有句话很有意思:
在编写这本书的过程中,我再一次感到,在不计其数的编程语言中,汇编语言是最‘有趣’的一种
配套资源在:https://github.com/shyujikou/binarybook
一、软件分析体验
首先是一些工具安装:
- 二进制编辑 WinHex:建议到吾爱破解下载
- 网络监控 Wireshark:https://www.wireshark.org/
- 文件和注册表监控 Process Monitor:https://docs.microsoft.com/zh-cn/sysinternals/downloads/procmon
- 反汇编 IDA:建议到吾爱破解下载
- 调试器 OllyDbg:建议到吾爱破解下载
本节要用到的是 chap01\\sample_mal\\Release 目录中的 sample_mal.exe 文件
1、通过 Process Monitor 的日志来确认程序的行为
sample_mal.exe 文件运行后,弹出一个内容为“Hello Malware!”的对话框,如下:
Process Monitor 的日志如下:
可以看到 sample_mal.exe 文件连续执行了 CreateFile、WriteFile 和 CloseFile 这几个操作,这些操作加起来的功能相当于在指定文件夹创建并写入一个名为 0.exe 的文件
进入C:\\Users\\ 用户名 \\AppData\\Roaming\\Microsoft\\Windows\\Start Menu\\Programs\\Startup
可以看到 0.exe
文件
用 Winhex 与 sample_mal.exe 文件进行对比,发现两个文件完全一致
此外,sample_mal.exe 还在 我的文档
目录下创建了1.exe
文件:
2、从注册表访问中能发现些什么
Windows 重启时自动运行的程序可以注册在下列任一注册表的位置:
- HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows\\CurrentVersion\\Run
- HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Run
- HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows\\CurrentVersion\\RunOnce
- HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\RunOnce
可以发现注册表里面的确注册了 C:\\Documents and Settings\\XPMUser\\My Documents\\1.exe
这样的内容
3、小结
通过上述,sample_mal.exe 程序会执行以下操作:
- 修改注册表以便在系统重启时自动运行
- 将自己复制到“启动”文件夹以便在系统重启时自动运行
因此,我们只要将“启动”文件夹、“我的文档”以及 注册表中新增的内容(文件路径)删除,系统环境就可以完全恢复原状 了
二、静态分析体验
静态分析与动态分析简单定义如下:
- 静态分析:在不运行目标程序的情况下进行分析
- 动态分析:在运行目标程序的同时进行分析
静态分析主要包括以下方法:
- 阅读反汇编代码
- 提取可执行文件中的字符串,分析使用了哪些单词
这里用到 chap01\\wsample01a\\Release 中的示例程序 wsample01a.exe
1、WinHex 查看文件内容
用 WinHex 打开 wsample01a.exe
可以看到这些内容:
- 字符串
MESSAGE
和Hello! Windows
- 文件路径
C:\\Documents and Settings\\XPMUser\\My Documents\\Visual Studio 2010\\Projects\\wsample01a\\Release\\wsample01a.pdb
- 字符串
KERNEL32.dll
、MessageBoxW
主要是感受下
2、IDA 反汇编
将 wsample01a.exe 扔进 IDA:
也是感受下
跟源码对比下:
#include <Windows.h>
#include <tchar.h>
int APIENTRY _tWinMain(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
if(lstrcmp(lpCmdLine, _T("2012")) == 0)
MessageBox(GetActiveWindow(),
_T("Hello! 2012"), _T("MESSAGE"), MB_OK);
else
MessageBox(GetActiveWindow(),
_T("Hello! Windows"), _T("MESSAGE"), MB_OK);
return 0;
三、动态分析体验
动态分析:
- 在目标程序运行的同时跟踪其行为,主要用调试器来跟踪程序逻辑
- 获取文件和注册表访问日志
- 抓取网络包
这里用 chap01\\wsample01b\\Release 中的示例程序 wsample01b.exe
1、 Process Monitor 跟踪
为了跟踪程序,设置 Process Monitor 的过滤规则:
然后可以发现其行为类似于开头的 sample_mal.exe
2、OllyDbg 调试
调试器是一种帮助发现程序问题和 bug 的软件:
- 断点
- 单步跳入、跳出
- 查看寄存器和内存数据
看看 00401000
之后的程序逻辑,发现程序依次调用了 GetModuleFileNameW
、SHGetFolderPathW
、lstrcatW
、 CopyFileW
这几个函数
通过设置断点和单步前进可以了解每一步或者说上面每一个函数在做什么
同样与源代码对比:
#include <Windows.h>
#include <tchar.h>
int APIENTRY _tWinMain(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
if(lstrcmp(lpCmdLine, _T("2012")) == 0)
MessageBox(GetActiveWindow(),
_T("Hello! 2012"), _T("MESSAGE"), MB_OK);
else
MessageBox(GetActiveWindow(),
_T("Hello! Windows"), _T("MESSAGE"), MB_OK);
return 0;
四、基础汇编指令
1、常用汇编指令
常用汇编指令如下:
指令 | 示例 | 含义 | 说明 |
---|---|---|---|
MOV | MOV EAX,ECX | EAX = ECX | 将 ECX 的值存入 EAX |
ADD | ADD EAX,ECX | EAX += ECX | 将 EAX 的值加上 ECX 的值 |
SUB | SUB EAX,ECX | EAX -= ECX | 将 EAX 的值减去 ECX 的值 |
INC | INC EAX | EAX++ | 将 EAX 的值加 1 |
DEC | DEC EAX | EAX– | 将 EAX 的值减 1 |
LEA | LEA EAX, [ECX+4] | EAX = ECX+4 | 将 ECX+4 的值存入 EAX |
CMP | CMP EAX,ECX | if(EAX == ECX) ZF=1 elseZF=0 | 对两个值进行比较并根据结果设置 标志若 EAX 与 ECX 相同,则 ZF=1 若 EAX 与 ECX 不同,则 ZF=0 |
TEST | TEST EAX,EAX | if(EAX == 0) ZF=1 elseZF=0 | 将值与 0 进行比较并根据结果设置 标志若 EAX 为 0,则 ZF=1 若 EAX 不为 0,则 ZF=0 |
JE(JZ) | JE 04001000 | if(ZF==1) GOTO 04001000 | 若 ZF 为 1,则跳转到 04001000 |
JNE(JNZ) | JNE 04001000 | if(ZF==0) GOTO 04001000 | 若 ZF 为 0,则跳转到 04001000 |
JMP | JMP 04001000 | GOTO 04001000 | 无条件跳转到 04001000 |
CALL | CALL lstrcmpW | 调用 lstrcmpW | |
PUSH | PUSH 00000001 | 将 00000001 入栈 | |
POP | POP EAX | 出栈并将获取的值存入 EAX |
JNZ 指令和 TEST 指令结合就是条件分支
2、参数存放在栈中
CALL 指令是用来调用子程序的,当我们用汇编语言编写子程序的时候,将返回值存放在 EAX 中,这是一种习惯
参数要通过 PUSH 指令存放在栈中:每当执行 PUSH 指令时,PUSH 的值就会被放入栈中
3、例子
一个 hello world 的汇编如下:
extern MessageBoxA
section .text
global main
main:
push dword 0
push dword title
push dword text
push dword 0
call MessageBoxA
ret
section .data
title: db 'MessageBox', 0
text: db 'Hello World!', 0
结语
主要是体验下几种最常用的逆向工具
以上是关于《有趣的二进制:软件安全与逆向分析》读书笔记:通过逆向工程学习如何读懂二进制代码的主要内容,如果未能解决你的问题,请参考以下文章
《有趣的二进制:软件安全与逆向分析》读书笔记:通过逆向工程学习如何读懂二进制代码
《有趣的二进制:软件安全与逆向分析》读书笔记:利用软件的漏洞进行攻击
《有趣的二进制:软件安全与逆向分析》读书笔记:利用软件的漏洞进行攻击
《有趣的二进制:软件安全与逆向分析》读书笔记:利用软件的漏洞进行攻击