1、课程目标
- 回顾整个x86/x64汇编章节的核心知识
- 通过综合项目巩固学习内容
- 掌握汇编在安全研究中的应用
- 为后续章节打下坚实基础
2、知识回顾
第一部分:x86基础
| 课时 |
核心内容 |
| 课时01 |
寄存器体系:EAX/EBX/ECX/EDX/ESI/EDI/ESP/EBP |
| 课时02 |
MASM框架、数据移动指令、段定义 |
| 课时03 |
数据类型、整数运算指令 |
| 课时04 |
位运算指令、XOR加密应用 |
| 课时05 |
寻址方式、有效地址计算 |
| 课时06 |
EFLAGS标志寄存器、条件判断 |
| 课时07 |
JCC条件跳转、循环实现 |
第二部分:进阶内容
| 课时 |
核心内容 |
| 课时08 |
函数调用、堆栈帧、调用约定 |
| 课时09 |
串指令、REP前缀、内存操作 |
| 课时10 |
结构体、宏定义、条件汇编 |
| 课时11 |
x64架构、新寄存器、调用约定 |
| 课时12 |
内联汇编、混合编程 |
| 课时13 |
Linux汇编、系统调用 |
3、综合实战项目
3.1、项目1:简单加密器
#include <stdio.h>
#include <string.h>
// XOR加密实现
void XorEncrypt(unsigned char* data, size_t len, unsigned char key) {
__asm {
mov esi, data
mov ecx, len
mov al, key
encrypt_loop:
test ecx, ecx
jz done
xor [esi], al
inc esi
dec ecx
jmp encrypt_loop
done:
}
}
// ROL/ROR加密
void RotateEncrypt(unsigned char* data, size_t len, unsigned char shift) {
__asm {
mov esi, data
mov ecx, len
mov cl, shift
rotate_loop:
cmp ecx, 0
je rotate_done
mov al, [esi]
rol al, cl ; 循环左移
mov [esi], al
inc esi
dec ecx
jmp rotate_loop
rotate_done:
}
}
int main() {
char plaintext[] = "Hello, Assembly!";
unsigned char key = 0x5A;
printf("Original: %s\n", plaintext);
XorEncrypt((unsigned char*)plaintext, strlen(plaintext), key);
printf("Encrypted: ");
for (size_t i = 0; i < strlen(plaintext); i++) {
printf("%02X ", (unsigned char)plaintext[i]);
}
printf("\n");
XorEncrypt((unsigned char*)plaintext, strlen(plaintext), key);
printf("Decrypted: %s\n", plaintext);
return 0;
}
3.2、项目2:内存扫描器
#include <windows.h>
#include <stdio.h>
// 在内存中搜索特征码
void* ScanMemory(void* start, size_t size, unsigned char* pattern, size_t patternLen) {
void* result = NULL;
__asm {
mov edi, start ; 搜索起始地址
mov ecx, size ; 搜索范围
scan_loop:
cmp ecx, patternLen
jb not_found
; 比较特征码
push ecx
push edi
mov esi, pattern
mov ecx, patternLen
repe cmpsb
pop edi
pop ecx
je found
inc edi
dec ecx
jmp scan_loop
found:
mov result, edi
jmp done
not_found:
mov result, 0
done:
}
return result;
}
int main() {
char testData[] = "AAAA_TARGET_BBBB";
unsigned char pattern[] = "TARGET";
void* found = ScanMemory(testData, sizeof(testData), pattern, sizeof(pattern)-1);
if (found) {
printf("Found at offset: %d\n", (int)((char*)found - testData));
} else {
printf("Not found\n");
}
return 0;
}
3.3、项目3:API哈希计算
#include <windows.h>
#include <stdio.h>
// 计算字符串哈希(常用于shellcode)
DWORD CalcHash(const char* str) {
DWORD hash;
__asm {
mov esi, str
xor eax, eax ; hash = 0
xor ecx, ecx ; 字符清零
hash_loop:
mov cl, [esi]
test cl, cl
jz hash_done
ror eax, 13 ; 循环右移13位
add eax, ecx ; 加上字符
inc esi
jmp hash_loop
hash_done:
mov hash, eax
}
return hash;
}
int main() {
printf("Hash of 'kernel32.dll': 0x%08X\n", CalcHash("kernel32.dll"));
printf("Hash of 'LoadLibraryA': 0x%08X\n", CalcHash("LoadLibraryA"));
printf("Hash of 'GetProcAddress': 0x%08X\n", CalcHash("GetProcAddress"));
printf("Hash of 'VirtualAlloc': 0x%08X\n", CalcHash("VirtualAlloc"));
return 0;
}
3.4、项目4:简单Hook实现
#include <windows.h>
#include <stdio.h>
// 原MessageBoxA地址
typedef int (WINAPI *pMessageBoxA)(HWND, LPCSTR, LPCSTR, UINT);
pMessageBoxA OriginalMessageBoxA = NULL;
// 保存原始字节
BYTE OriginalBytes[5] = {0};
// 我们的Hook函数
int WINAPI HookedMessageBoxA(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType) {
printf("[HOOK] MessageBoxA called!\n");
printf(" Text: %s\n", lpText);
printf(" Caption: %s\n", lpCaption);
// 恢复原始字节
DWORD oldProtect;
VirtualProtect(OriginalMessageBoxA, 5, PAGE_EXECUTE_READWRITE, &oldProtect);
memcpy(OriginalMessageBoxA, OriginalBytes, 5);
VirtualProtect(OriginalMessageBoxA, 5, oldProtect, &oldProtect);
// 调用原函数
int result = OriginalMessageBoxA(hWnd, "[Hooked Message]", lpCaption, uType);
return result;
}
void InstallHook() {
// 获取原函数地址
HMODULE hUser32 = GetModuleHandleA("user32.dll");
OriginalMessageBoxA = (pMessageBoxA)GetProcAddress(hUser32, "MessageBoxA");
// 保存原始字节
memcpy(OriginalBytes, OriginalMessageBoxA, 5);
// 计算跳转偏移
DWORD hookOffset = (DWORD)HookedMessageBoxA - (DWORD)OriginalMessageBoxA - 5;
// 写入JMP指令
DWORD oldProtect;
VirtualProtect(OriginalMessageBoxA, 5, PAGE_EXECUTE_READWRITE, &oldProtect);
__asm {
mov edi, OriginalMessageBoxA
mov byte ptr [edi], 0xE9 ; JMP opcode
mov eax, hookOffset
mov [edi+1], eax ; 偏移量
}
VirtualProtect(OriginalMessageBoxA, 5, oldProtect, &oldProtect);
}
int main() {
printf("Installing hook...\n");
InstallHook();
printf("Calling MessageBoxA...\n");
MessageBoxA(NULL, "Original Message", "Test", MB_OK);
return 0;
}
3.5、项目5:x64寄存器读取器
#include <windows.h>
#include <stdio.h>
void PrintRegisters() {
CONTEXT ctx = {0};
ctx.ContextFlags = CONTEXT_FULL;
// 获取当前线程上下文
HANDLE hThread = GetCurrentThread();
// 使用RtlCaptureContext
RtlCaptureContext(&ctx);
#ifdef _WIN64
printf("=== x64 Registers ===\n");
printf("RAX: 0x%016llX\n", ctx.Rax);
printf("RBX: 0x%016llX\n", ctx.Rbx);
printf("RCX: 0x%016llX\n", ctx.Rcx);
printf("RDX: 0x%016llX\n", ctx.Rdx);
printf("RSI: 0x%016llX\n", ctx.Rsi);
printf("RDI: 0x%016llX\n", ctx.Rdi);
printf("RBP: 0x%016llX\n", ctx.Rbp);
printf("RSP: 0x%016llX\n", ctx.Rsp);
printf("R8: 0x%016llX\n", ctx.R8);
printf("R9: 0x%016llX\n", ctx.R9);
printf("R10: 0x%016llX\n", ctx.R10);
printf("R11: 0x%016llX\n", ctx.R11);
printf("R12: 0x%016llX\n", ctx.R12);
printf("R13: 0x%016llX\n", ctx.R13);
printf("R14: 0x%016llX\n", ctx.R14);
printf("R15: 0x%016llX\n", ctx.R15);
printf("RIP: 0x%016llX\n", ctx.Rip);
#else
printf("=== x86 Registers ===\n");
printf("EAX: 0x%08lX\n", ctx.Eax);
printf("EBX: 0x%08lX\n", ctx.Ebx);
printf("ECX: 0x%08lX\n", ctx.Ecx);
printf("EDX: 0x%08lX\n", ctx.Edx);
printf("ESI: 0x%08lX\n", ctx.Esi);
printf("EDI: 0x%08lX\n", ctx.Edi);
printf("EBP: 0x%08lX\n", ctx.Ebp);
printf("ESP: 0x%08lX\n", ctx.Esp);
printf("EIP: 0x%08lX\n", ctx.Eip);
#endif
printf("\n=== Flags ===\n");
printf("EFlags: 0x%08lX\n", ctx.EFlags);
printf(" CF=%d ZF=%d SF=%d OF=%d\n",
(ctx.EFlags >> 0) & 1,
(ctx.EFlags >> 6) & 1,
(ctx.EFlags >> 7) & 1,
(ctx.EFlags >> 11) & 1);
}
int main() {
PrintRegisters();
return 0;
}
4、汇编指令速查表
4.1、数据移动
| 指令 |
说明 |
| MOV |
数据传送 |
| LEA |
加载有效地址 |
| PUSH/POP |
栈操作 |
| XCHG |
交换数据 |
4.2、算术运算
| 指令 |
说明 |
| ADD/SUB |
加/减 |
| MUL/IMUL |
无符号/有符号乘 |
| DIV/IDIV |
无符号/有符号除 |
| INC/DEC |
加一/减一 |
4.3、位运算
| 指令 |
说明 |
| AND/OR/XOR |
与/或/异或 |
| NOT/NEG |
取反/取负 |
| SHL/SHR |
逻辑左移/右移 |
| SAL/SAR |
算术左移/右移 |
| ROL/ROR |
循环左移/右移 |
4.4、控制流
| 指令 |
说明 |
| JMP |
无条件跳转 |
| JE/JZ |
相等跳转 |
| JNE/JNZ |
不相等跳转 |
| JG/JL |
有符号大于/小于 |
| JA/JB |
无符号大于/小于 |
| CALL/RET |
调用/返回 |
5、课后作业
- 综合项目:结合所学内容,实现一个完整的内存修改器
- 深入研究:分析一个简单程序的汇编代码,理解编译器优化
- 实战应用:尝试编写一段位置无关的shellcode
- 跨平台:将Windows汇编程序移植到Linux