欢迎光临
我们一直在努力

x32dbg/x64dbg逆向之反向分析局部变量

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;
}

赞(0)
未经允许不得转载:171主机测评 » x32dbg/x64dbg逆向之反向分析局部变量
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址