





x32dbg/x64dbg逆向之反向分析局部变量
1) 反向分析局部变量
使用咱们上节课的内容ds指向数据段(全局/静态变量),ss 指向 栈段(局部变量)
咱们结合上节课的知识点展开学习。在汇编语言的内存分段机制中,不同寄存器对应着不同的内存段区域,功能划分十分明确。其中ds寄存器专门指向数据段,这片内存区域主要用于存放程序里的全局变量与静态变量,数据生命周期较长。而ss寄存器则指向栈段栈段是运行时动态变化的内存空间,程序中的局部变量都会存储在这里。咱们掌握ds和ss两个寄存器对应的内存分区,是反向分析局部变量的基础,能帮助咱们快速定位变量所在位置。
2)C语言案例代码
咱们在学习逆向分析的同时,同步梳理C和C++基础知识点,一正一反(正向开发,逆向分析)为后续深耕底层技术打好基础哦。
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
// Test function for function pointer
void testFunc(int x)
{
printf("Function pointer call, x = %d\\n", x);
}
int main(void)
{
// ===================== All Common C Data Types =====================
// Basic integer types
char valChar = 'Z';
unsigned char valUchar = 255;
short valShort = 100;
unsigned short valUshort = 200;
int valInt = 999;
unsigned int valUint = 1024;
long valLong = 123456L;
unsigned long valUlong = 654321UL;
long long valLlong = 1122334455LL;
unsigned long long valUllong = 9988776655ULL;
// Float types
float valFloat = 3.14f;
double valDouble = 6.28;
long double valLdouble = 9.99L;
// Boolean type
bool valBool = true;
// String & character array
char* valPChar = (char*)"Hello All Types";
char** valPPchar = NULL;
char valCharArr[100] = "Char Array Content";
// Void pointer
int temp = 888;
void* valPVoid = &temp;
// Custom struct
struct Student
{
// Bit-field type
unsigned int age : 8;
unsigned int sex : 1;
int id;
};
struct Student valStu = { 20, 1, 2025001 };
// Union type
union Data
{
int num;
char ch;
float f;
};
union Data valUnion = { 520 };
// Enum type
enum Color
{
BLACK, WHITE, RED, BLUE
};
enum Color valColor = RED;
// Array pointer function pointer
int valArr[5] = { 0 };
int (*valPArr)[5] = &valArr;
void (*valPFunc)(int) = testFunc;
// ==========================================================================
// Call function pointer
valPFunc(666);
printf("char : %c\\n", valChar);
printf("uchar : %u\\n", valUchar);
printf("short : %d\\n", valShort);
printf("int : %d\\n", valInt);
printf("long long : %lld\\n", valLlong);
printf("float : %.2f\\n", valFloat);
printf("double : %.2lf\\n", valDouble);
printf("bool : %d\\n", valBool);
printf("str pointer : %s\\n", valPChar);
printf("char array : %s\\n", valCharArr);
printf("enum color : %d\\n", valColor);
printf("struct age : %d\\n", valStu.age);
printf("union num : %d\\n", valUnion.num);
return 0;
}
3)反向分析局部变量
咱们就用之前讲过的规则,来一步步分析这段汇编代码,核心就抓一个关键点:只要指令里看到ds:,那操作的肯定就是全局/静态变量;看到ss:,操作的就是局部变量,照着这个思路看就行。
x64
00007FF7F1871890 | 40:55 | push rbp | 创建栈帧,保存rbp,rsi,rdi
00007FF7F1871892 | 56 | push rsi |
00007FF7F1871893 | 57 | push rdi |
00007FF7F1871894 | 48:81EC 50050000 | sub rsp,550 | 栈指针下移0x550字节,开辟局部变量栈空间
00007FF7F187189B | 48:8D6C24 20 | lea rbp,qword ptr ss:[rsp+20] | 将rbp设为rsp+0x20,作为当前函数栈帧基准地址
00007FF7F18718A0 | 48:8D7C24 20 | lea rdi,qword ptr ss:[rsp+20] | 把栈起始地址载入rdi,准备批量填充栈
00007FF7F18718A5 | B9 EC000000 | mov ecx,EC | 填充计数ecx=0xEC,控制rep循环次数
00007FF7F18718AA | B8 CCCCCCCC | mov eax,CCCCCCCC |
00007FF7F18718AF | F3:AB | rep stosd | 循环批量将eax(0xCCCCCCCC)写入rdi指向栈
00007FF7F18718B1 | 48:8B05 88C70000 | mov rax,qword ptr ds:[<__security_cooki | 读取全局栈保护随机Cookie值到rax rax:__enc$textbss$end+5A
00007FF7F18718B8 | 48:33C5 | xor rax,rbp | Cookie异或当前栈基址rbp,加密存储Cookie防直接篡改rax:__enc$textbss$end+5A
00007FF7F18718BB | 48:8985 20050000 | mov qword ptr ss:[rbp+520],rax | 加密后的Cookie存入栈高位预留位置,函数结尾校验 rax:__enc$textbss$end+5A
00007FF7F18718C2 | 48:8D0D 46170100 | lea rcx,qword ptr ds:[<__14F49BB1_FileN | 读取全局常量字符串地址到rcx,调用初始化子函数 FileName.cpp:15732480
00007FF7F18718C9 | E8 D4FAFFFF | call project1.7FF7F18713A2 | 调用全局数据/字符串初始化内部函数
00007FF7F18718CE | 90 | nop |
00007FF7F18718CF | C645 04 5A | mov byte ptr ss:[rbp+4],5A | 局部char变量赋值'Z'(0x5A),存入栈rbp+0x04 FileName.cpp:16, 5A:'Z'
00007FF7F18718D3 | C645 24 FF | mov byte ptr ss:[rbp+24],FF | 局部unsigned char变量赋值0xFF,存入栈rbp+0x24 FileName.cpp:17
00007FF7F18718D7 | B8 64000000 | mov eax,64 | 立即数0x64(100)载入eax FileName.cpp:18, 64:'d'
00007FF7F18718DC | 66:8945 44 | mov word ptr ss:[rbp+44],ax | 局部short变量赋值100,存入栈rbp+0x44(2字节word)
00007FF7F18718E0 | B8 C8000000 | mov eax,C8 | 立即数0xC8(200)载入eax FileName.cpp:19
00007FF7F18718E5 | 66:8945 64 | mov word ptr ss:[rbp+64],ax | 局部short变量赋值200,存入栈rbp+0x64(2字节word)
00007FF7F18718E9 | C785 84000000 E7030000 | mov dword ptr ss:[rbp+84],3E7 | 局部int变量赋值0x3E7(999),存入栈rbp+0x84(4字节dword)FileName.cpp:20
00007FF7F18718F3 | C785 A4000000 00040000 | mov dword ptr ss:[rbp+A4],400 | 局部int变量赋值0x400(1024),存入栈rbp+0xA4 FileName.cpp:21
00007FF7F18718FD | C785 C4000000 40E20100 | mov dword ptr ss:[rbp+C4],1E240 | 局部int变量赋值0x1E240(123456),存入栈rbp+0xC4 FileName.cpp:22
00007FF7F1871907 | C785 E4000000 F1FB0900 | mov dword ptr ss:[rbp+E4],9FBF1 | 局部int变量赋值0x9FBF1(654833),存入栈rbp+0xE4 FileName.cpp:23
00007FF7F1871911 | 48:C785 08010000 F776E54 | mov qword ptr ss:[rbp+108],42E576F7 | 局部long long变量赋值0x42E576F7,存入栈rbp+0x108(8字节qword)FileName.cpp:24
00007FF7F187191C | 48:B8 CFA2605302000000 | mov rax,25360A2CF | 64位立即数0x25360A2CF载入rax FileName.cpp:25, rax:__enc$textbss$end+5A
00007FF7F1871926 | 48:8985 28010000 | mov qword ptr ss:[rbp+128],rax | 另一long long变量存入rbp+0x128 rax:__enc$textbss$end+5A
00007FF7F187192D | F3:0F1005 8F960000 | movss xmm0,dword ptr ds:[<__real@4048f5 | 读取全局float常量到浮点寄存器xmm0(单精度浮点数)FileName.cpp:28
00007FF7F1871935 | F3:0F1185 44010000 | movss dword ptr ss:[rbp+144],xmm0 | float存入栈rbp+0x144(4字节单精度)
00007FF7F187193D | F2:0F1005 63960000 | movsd xmm0,qword ptr ds:[<__real@40191e | 读取全局double常量到xmm0(双精度浮点数)FileName.cpp:29
00007FF7F1871945 | F2:0F1185 68010000 | movsd qword ptr ss:[rbp+168],xmm0 | double存入栈rbp+0x168(8字节双精度)
00007FF7F187194D | F2:0F1005 63960000 | movsd xmm0,qword ptr ds:[<__real@4023fa | 读取第二个全局double常量到xmm0 FileName.cpp:30
00007FF7F1871955 | F2:0F1185 88010000 | movsd qword ptr ss:[rbp+188],xmm0 | 第二个double存入栈rbp+0x188
00007FF7F187195D | C685 A4010000 01 | mov byte ptr ss:[rbp+1A4],1 | 局部bool变量赋值true(1),存入rbp+0x1A4 FileName.cpp:33
00007FF7F1871964 | 48:8D05 CD940000 | lea rax,qword ptr ds:[<"Hello All Types | 取字符串"Hello All Types"地址存入rax FileName.cpp:36, rax:__enc$textbss$end+5A, 00007FF728DCAE38:"Hello All Types"
00007FF7F187196B | 48:8985 C8010000 | mov qword ptr ss:[rbp+1C8],rax | 字符串指针存入栈rbp+0x1C8(char*类型)rax:__enc$textbss$end+5A
00007FF7F1871972 | 48:C785 E8010000 0000000 | mov qword ptr ss:[rbp+1E8],0 | 初始化另一个指针变量为nullptr(0) FileName.cpp:37
00007FF7F187197D | 48:8D85 10020000 | lea rax,qword ptr ss:[rbp+210] | 取栈rbp+0x210地址,作为char字符数组首地址 rax:__enc$textbss$end+5A FileName.cpp:38
00007FF7F1871984 | 48:8D0D C5940000 | lea rcx,qword ptr ds:[<"Char Array Cont | 取源字符串"Char Array Content"地址 00007FF728DCAE50:"Char Array Content"
00007FF7F187198B | 48:8BF8 | mov rdi,rax | 目标数组地址载入rdi rax:__enc$textbss$end+5A
00007FF7F187198E | 48:8BF1 | mov rsi,rcx | 源字符串地址载入rsi
00007FF7F1871991 | B9 13000000 | mov ecx,13 | 拷贝长度ecx=0x13(19)个字符
00007FF7F1871996 | F3:A4 | rep movsb | 循环内存拷
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
// Test function for function pointer
void testFunc(int x)
{
printf("Function pointer call, x = %d\\n", x);
}
int main(void)
{
// ===================== All Common C Data Types =====================
// Basic integer types
char valChar = 'Z';
unsigned char valUchar = 255;
short valShort = 100;
unsigned short valUshort = 200;
int valInt = 999;
unsigned int valUint = 1024;
long valLong = 123456L;
unsigned long valUlong = 654321UL;
long long valLlong = 1122334455LL;
unsigned long long valUllong = 9988776655ULL;
// Float types
float valFloat = 3.14f;
double valDouble = 6.28;
long double valLdouble = 9.99L;
// Boolean type
bool valBool = true;
// String & character array
char* valPChar = (char*)"Hello All Types";
char** valPPchar = NULL;
char valCharArr[100] = "Char Array Content";
// Void pointer
int temp = 888;
void* valPVoid = &temp;
// Custom struct
struct Student
{
// Bit-field type
unsigned int age : 8;
unsigned int sex : 1;
int id;
};
struct Student valStu = { 20, 1, 2025001 };
// Union type
union Data
{
int num;
char ch;
float f;
};
union Data valUnion = { 520 };
// Enum type
enum Color
{
BLACK, WHITE, RED, BLUE
};
enum Color valColor = RED;
// Array pointer function pointer
int valArr[5] = { 0 };
int (*valPArr)[5] = &valArr;
void (*valPFunc)(int) = testFunc;
// ==========================================================================
// Call function pointer
valPFunc(666);
printf("char : %c\\n", valChar);
printf("uchar : %u\\n", valUchar);
printf("short : %d\\n", valShort);
printf("int : %d\\n", valInt);
printf("long long : %lld\\n", valLlong);
printf("float : %.2f\\n", valFloat);
printf("double : %.2lf\\n", valDouble);
printf("bool : %d\\n", valBool);
printf("str pointer : %s\\n", valPChar);
printf("char array : %s\\n", valCharArr);
printf("enum color : %d\\n", valColor);
printf("struct age : %d\\n", valStu.age);
printf("union num : %d\\n", valUnion.num);
return 0;
}



