Windows程序字符串处理与逆向分析

Windows程序字符串处理与逆向分析

文章目录

  • Windows程序字符串处理与逆向分析
    • [1. 字符串类型](#1. 字符串类型)
      • [1.1 C风格字符串 (char*)](#1.1 C风格字符串 (char*))
      • [1.2 宽字符字符串 (wchar_t*)](#1.2 宽字符字符串 (wchar_t*))
      • [1.3 C++标准字符串](#1.3 C++标准字符串)
    • [2. 字符串处理函数](#2. 字符串处理函数)
      • [2.1 字符串长度计算 - strlen](#2.1 字符串长度计算 - strlen)
      • [2.2 字符串复制 - strcpy/strncpy](#2.2 字符串复制 - strcpy/strncpy)
      • [2.3 字符串比较 - strcmp](#2.3 字符串比较 - strcmp)
      • [2.4 字符串搜索 - strstr](#2.4 字符串搜索 - strstr)
    • [3. 字符串存储方式](#3. 字符串存储方式)
      • [3.1 不同存储位置的汇编特征](#3.1 不同存储位置的汇编特征)
    • [4. 安全与混淆技术](#4. 安全与混淆技术)
      • [4.1 字符串加密的汇编实现](#4.1 字符串加密的汇编实现)
      • [4.2 安全字符串处理的汇编对比](#4.2 安全字符串处理的汇编对比)
    • 逆向工程实战技巧

1. 字符串类型

1.1 C风格字符串 (char*)

代码示例:

c 复制代码
#include <stdio.h>
#include <string.h>

void demonstrate_c_string() {
    char str1[] = "Hello World";
    char* str4 = malloc(20);
    strcpy(str4, "Dynamic String");
    
    printf("str1: %s\n", str1);
    
    // 内联汇编详细解释
    __asm {
        ; === 汇编解释:访问C风格字符串 ===
        mov esi, offset str1      ; ESI = 字符串首地址(在x86中,offset获取标号地址)
        ; 在内存中:48 65 6C 6C 6F 20 57 6F 72 6C 64 00 ("Hello World"的ASCII)
        
        mov al, [esi]             ; AL = 字节[ESI] = 'H' (0x48)
        ; 这是直接内存访问,ESI是基地址,[ESI]表示该地址处的字节
        
        mov bl, [esi + 1]         ; BL = 字节[ESI+1] = 'e' (0x65)
        ; 通过基地址+偏移量访问字符串中的特定字符
        
        ; === 逆向工程识别特征 ===
        ; 1. 连续字节序列,以00结尾
        ; 2. 常见访问模式:mov reg, [base + index]
        ; 3. 循环通常以cmp byte ptr [reg], 0检测结束
    }
    
    free(str4);
}

汇编层详细分析:

assembly 复制代码
; 编译后在.data段或栈上的实际布局
_str1 db 'H','e','l','l','o',' ','W','o','r','l','d',0
; 内存地址: 0x00403000: 48 65 6C 6C 6F 20 57 6F 72 6C 64 00

; 访问字符串的典型汇编代码
mov eax, offset _str1    ; EAX = 0x00403000 (字符串起始地址)
mov cl, [eax]            ; CL = 0x48 ('H')
inc eax                  ; EAX = 0x00403001  
mov cl, [eax]            ; CL = 0x65 ('e')

1.2 宽字符字符串 (wchar_t*)

代码示例:

c 复制代码
#include <stdio.h>
#include <wchar.h>

void demonstrate_wide_string() {
    wchar_t wstr1[] = L"Hello World";
    wchar_t* wstr3 = malloc(20 * sizeof(wchar_t));
    wcscpy(wstr3, L"宽字符串");
    
    // 内联汇编详细解释
    __asm {
        ; === 汇编解释:访问宽字符串 ===
        mov esi, offset wstr1     ; ESI指向宽字符串首地址
        ; 内存布局:48 00 65 00 6C 00 6C 00 6F 00 20 00 57 00 6F 00 72 00 6C 00 64 00 00 00
        ; 小端序:低字节在前,所以'H'存储为0x0048
        
        mov ax, [esi]             ; AX = 字[ESI] = 0x0048 ('H')
        ; 注意:这里用AX(16位)而不是AL(8位),因为宽字符是2字节
        
        mov bx, [esi + 2]         ; BX = 字[ESI+2] = 0x0065 ('e')
        ; 每个字符占2字节,所以+2而不是+1
        
        ; === 逆向工程识别特征 ===
        ; 1. 内存中每2字节一组,以0000结尾
        ; 2. 使用字(word)操作而不是字节(byte)操作
        ; 3. Windows API调用使用stdcall,参数从右向左压栈
    }
    
    free(wstr3);
}

宽字符串汇编细节:

assembly 复制代码
; 宽字符串在内存中的实际存储
_wstr1 dw 0048h, 0065h, 006Ch, 006Ch, 006Fh, 0020h, 0057h, 006Fh, 0072h, 006Ch, 0064h, 0000h
; 或者以字节形式:48 00 65 00 6C 00 6C 00 6F 00 20 00 57 00 6F 00 72 00 6C 00 64 00 00 00

; 宽字符串操作的典型汇编
mov edi, offset _wstr1   ; EDI指向宽字符串
mov ax, [edi]            ; AX = 'H' (0x0048)
add edi, 2               ; 宽字符:每次+2字节
mov ax, [edi]            ; AX = 'e' (0x0065)

; 宽字符串函数调用(MessageBoxW)
push 0                   ; uType = MB_OK
push offset _wtitle      ; lpCaption  
push offset _wstr1       ; lpText (宽字符串)
push 0                   ; hWnd = NULL
call MessageBoxW         ; 调用宽字符版本API

1.3 C++标准字符串

代码示例:

cpp 复制代码
#include <string>

void demonstrate_cpp_string() {
    std::string str1 = "Hello World";
    const char* c_str = str1.c_str();
    
    // 内联汇编详细解释
    __asm {
        ; === 汇编解释:std::string内部结构 ===
        mov ecx, offset str1      ; ECX指向string对象(this指针)
        ; std::string典型内存布局(MSVC实现):
        ; [ECX]     : 字符串数据指针(或小型字符串优化时的内联缓冲区)
        ; [ECX+4]   : 字符串长度
        ; [ECX+8]   : 缓冲区容量
        
        mov eax, [ecx]            ; EAX = 字符串数据指针
        ; 如果是小型字符串优化(SSO),[ECX]可能直接包含字符串内容
        
        mov cl, [eax]             ; CL = 第一个字符
        
        ; === 逆向工程识别特征 ===
        ; 1. 识别std::basic_string模板的虚函数表
        ; 2. 常见函数调用:call std::basic_string<char>::c_str
        ; 3. 小型字符串优化(SSO):字符串直接存储在对象内部
    }
}

std::string逆向分析特征:

assembly 复制代码
; MSVC中std::string的典型汇编模式
lea ecx, [ebp+str1]              ; ECX = this指针(std::string对象地址)
call std::basic_string<char,std::char_traits<char>,std::allocator<char>>::c_str
; 返回值为EAX,指向字符串数据

; 或者直接访问内部结构(依赖具体实现)
mov eax, [ebp+str1]              ; 假设这是数据指针
mov cl, byte ptr [eax]           ; 读取第一个字符

; 小型字符串优化(SSO)的识别
; 当字符串较短时,可能直接存储在栈上的string对象内
; 而不是通过指针访问堆内存

2. 字符串处理函数

2.1 字符串长度计算 - strlen

汇编层详细解释:

c 复制代码
#include <string.h>

void demonstrate_strlen() {
    char str[] = "Reverse Engineering";
    size_t len = strlen(str);
    
    // 内联汇编展示strlen工作原理
    __asm {
        ; === 汇编解释:strlen实现原理 ===
        mov edi, str              ; EDI指向字符串开始
        xor ecx, ecx              ; ECX = 0
        dec ecx                   ; ECX = 0xFFFFFFFF (最大计数值)
        xor al, al                ; AL = 0 (要扫描的终止字节)
        
        repne scasb               ; 重复执行:扫描字节[EDI]与AL比较
        ; 工作原理:
        ; 1. 比较[EDI]与AL (0)
        ; 2. 如果相等,ZF=1,停止
        ; 3. 否则EDI++,ECX--
        ; 4. 重复直到ECX=0或找到匹配
        
        not ecx                   ; 对ECX取反:0xFFFFFFFE -> 0x00000001
        dec ecx                   ; ECX--,得到实际长度
        mov len, ecx
        
        ; === 指令细节 ===
        ; REPNE: Repeat While Not Equal - 当ZF=0且ECX≠0时重复
        ; SCASB: Scan String Byte - 比较AL与[EDI],并设置EDI++
        ; 最终EDI指向终止字节后一个位置,ECX包含剩余计数
    }
}

strlen的多种汇编实现:

assembly 复制代码
; 方法1:使用repne scasb(编译器优化版本)
strlen_repne:
    mov edi, [esp+4]           ; 字符串指针
    mov ecx, -1                ; 最大计数
    xor eax, eax               ; 搜索0字节
    repne scasb                ; 扫描直到找到0
    not ecx                    ; 计算长度
    dec ecx
    mov eax, ecx
    ret

; 方法2:手动循环(调试版本更易读)
strlen_loop:
    mov edx, [esp+4]           ; 字符串指针
    xor eax, eax               ; 长度计数器
scan_loop:
    cmp byte ptr [edx+eax], 0  ; 检查当前字符是否为0
    je found_end               ; 如果是,跳转到结束
    inc eax                    ; 否则计数器+1
    jmp scan_loop              ; 继续循环
found_end:
    ret

; 方法3:优化手动循环(一次检查4字节)
strlen_optimized:
    mov edx, [esp+4]           ; 字符串指针
    mov eax, edx               ; EAX也指向开始
align_loop:
    test edx, 3                ; 检查是否4字节对齐
    jz aligned                 ; 如果对齐,继续
    cmp byte ptr [edx], 0      ; 检查当前字节
    je found                   ; 如果是0,结束
    inc edx                    ; 指针前进
    jmp align_loop             ; 继续对齐循环

2.2 字符串复制 - strcpy/strncpy

汇编层详细解释:

c 复制代码
#include <string.h>

void demonstrate_strcpy() {
    char src[] = "Copy this string";
    char dest[50];
    
    strcpy(dest, src);
    
    // 内联汇编展示strcpy工作原理
    __asm {
        ; === 汇编解释:strcpy实现 ===
        mov esi, offset src       ; ESI = 源字符串指针
        mov edi, offset dest      ; EDI = 目标缓冲区指针
        cld                       ; 清除方向标志DF=0(向前移动)
        
copy_loop:
        mov al, [esi]            ; AL = 当前源字符
        mov [edi], al            ; [EDI] = AL (复制到目标)
        inc esi                  ; 源指针前进
        inc edi                  ; 目标指针前进
        test al, al              ; 检查刚复制的字符是否为0
        jnz copy_loop            ; 如果不是0,继续循环
        
        ; === 优化版本使用rep movsb ===
        mov esi, offset src
        mov edi, offset dest
        mov ecx, length_of_src   ; 如果知道长度,可以更快
        rep movsb                ; 重复复制ECX次
        
        ; === 安全风险分析 ===
        ; 如果src长度 > dest缓冲区大小,会导致缓冲区溢出
        ; 攻击者可能覆盖返回地址或重要数据
    }
}

strcpy安全漏洞的汇编表现:

assembly 复制代码
; 不安全的strcpy使用
push offset src_string    ; 源字符串(可能很长)
push offset small_buffer  ; 小缓冲区(比如16字节)
call strcpy               ; 危险的调用!
add esp, 8

; 攻击场景:
; [栈布局]
; 0028FF00: small_buffer (16字节)    <- 可能被覆盖
; 0028FF10: 保存的EBP               <- 被覆盖导致栈破坏
; 0028FF14: 返回地址                <- 被覆盖可能执行恶意代码
; 0028FF18: 其他重要数据            <- 全部被破坏

; 安全版本:strncpy
push 16                   ; 最大复制长度
push offset src_string    ; 源字符串
push offset small_buffer  ; 目标缓冲区
call strncpy              ; 安全的复制
add esp, 12

2.3 字符串比较 - strcmp

汇编层详细解释:

c 复制代码
#include <string.h>

void demonstrate_strcmp() {
    char str1[] = "password";
    char str2[] = "password";
    int result = strcmp(str1, str2);
    
    // 内联汇编展示strcmp工作原理
    __asm {
        ; === 汇编解释:strcmp实现 ===
        mov esi, offset str1      ; ESI = 第一个字符串
        mov edi, offset str2      ; EDI = 第二个字符串
        
compare_loop:
        mov al, [esi]            ; AL = str1的当前字符
        mov bl, [edi]            ; BL = str2的当前字符
        cmp al, bl               ; 比较两个字符
        jne different            ; 如果不相等,跳转
        
        test al, al              ; 检查是否到达字符串结尾(0)
        jz equal                 ; 如果都是0,字符串相等
        
        inc esi                  ; 移动到下一个字符
        inc edi
        jmp compare_loop         ; 继续比较
        
equal:
        xor eax, eax             ; 返回0(相等)
        jmp done
        
different:
        sbb eax, eax             ; 巧妙设置返回值
        or al, 1                 ; 如果不相等,返回-1或1
        ; 具体:如果AL<BL,返回-1;如果AL>BL,返回1
        
done:
        mov result, eax
        
        ; === 优化版本使用repe cmpsb ===
        mov esi, offset str1
        mov edi, offset str2
        mov ecx, 0FFFFFFFFh      ; 最大比较长度
        repe cmpsb               ; 重复比较直到不相等
        ; 结束后:[ESI-1]和[EDI-1]是不相等的字符位置
    }
}

strcmp在逆向工程中的关键作用:

assembly 复制代码
; 序列号检查的典型模式
call get_user_input       ; 获取用户输入
push eax                  ; 用户输入的序列号
push offset valid_serial  ; 正确的序列号
call strcmp
add esp, 8
test eax, eax             ; 检查返回值
jnz invalid_serial        ; 如果不等于0,跳转到错误处理

; 密码验证模式
mov esi, user_password
mov edi, correct_password
compare_loop:
    mov al, [esi]
    cmp al, [edi]
    jnz access_denied     ; 任何一个字符不匹配就拒绝
    test al, al
    jz access_granted     ; 同时到达结尾,验证通过
    inc esi
    inc edi
    jmp compare_loop

access_granted:
    ; 验证成功的代码
access_denied:
    ; 验证失败的代码

2.4 字符串搜索 - strstr

汇编层详细解释:

c 复制代码
#include <string.h>

void demonstrate_strstr() {
    char text[] = "The quick brown fox jumps over the lazy dog";
    char keyword[] = "fox";
    char* found = strstr(text, keyword);
    
    // 内联汇编展示strstr工作原理
    __asm {
        ; === 汇编解释:strstr实现 ===
        mov esi, offset text      ; ESI = 主字符串
        mov edi, offset keyword   ; EDI = 要查找的子串
        
outer_loop:
        mov al, [esi]            ; AL = 主字符串当前字符
        test al, al              ; 检查是否主字符串结束
        jz not_found             ; 如果结束,没找到
        
        mov al, [edi]            ; AL = 子串第一个字符
        cmp al, [esi]            ; 比较第一个字符
        jne next_char            ; 不匹配,检查下一个位置
        
        ; 第一个字符匹配,检查剩余字符
        push esi                 ; 保存主字符串当前位置
        push edi                 ; 保存子串开始位置
        mov ecx, 0               ; 偏移量计数器
        
check_inner:
        mov al, [edi + ecx]      ; 子串当前字符
        test al, al              ; 子串结束?
        jz found_substring       ; 全部匹配成功!
        
        cmp al, [esi + ecx]      ; 比较主字符串对应位置
        jne next_char_pop        ; 不匹配,继续外层循环
        
        inc ecx                  ; 匹配,检查下一个字符
        jmp check_inner
        
next_char_pop:
        pop edi                  ; 恢复寄存器
        pop esi
        
next_char:
        inc esi                  ; 主字符串位置前进
        jmp outer_loop
        
found_substring:
        pop edi                  ; 清理栈
        pop edi                  ; 注意:这里弹出但不恢复ESI
        mov found, esi           ; 返回匹配开始位置
        jmp done
        
not_found:
        mov found, 0             ; 返回NULL
        
done:
        ; === 性能考虑 ===
        ; 实际实现会使用更高效的算法如Boyer-Moore
        ; 但基本原理相同:外层循环主串,内层循环比较子串
    }
}

3. 字符串存储方式

3.1 不同存储位置的汇编特征

详细汇编分析:

c 复制代码
#include <stdio.h>
#include <stdlib.h>

// 全局变量 - .data段
char global_str[] = "Global String";

// 常量 - .rdata段(只读)
const char* const_str = "Constant String";

void demonstrate_storage() {
    // 栈分配
    char stack_str[] = "Stack String";
    
    // 堆分配
    char* heap_str = malloc(50);
    strcpy(heap_str, "Heap String");
    
    // 内联汇编展示不同存储位置的访问
    __asm {
        ; === 全局变量访问 ===
        mov eax, offset global_str
        ; 编译时确定地址,如:mov eax, 00403000h
        mov cl, [eax]            ; 直接内存访问
        
        ; === 栈变量访问 ===  
        lea edx, [ebp-20]        ; stack_str在栈上的位置
        ; EBP是栈帧基址,局部变量通过EBP-偏移访问
        mov bl, [edx]            ; 访问栈上数据
        
        ; === 堆变量访问 ===
        mov esi, heap_str        ; ESI = 堆分配的内存地址
        ; 堆地址运行时确定,需要通过指针间接访问
        mov dl, [esi]            ; 间接内存访问
        
        ; === 常量访问 ===
        mov edi, const_str       ; EDI = 常量字符串地址
        mov al, [edi]            ; 访问只读内存段
    }
    
    free(heap_str);
}

各存储段的具体汇编表现:

assembly 复制代码
; 编译后的内存布局示例
.data                           ; 可读写数据段
global_str db 'Global String',0 ; 00403000

.rdata                          ; 只读数据段  
const_str dd offset aConstant   ; 00404000
aConstant db 'Constant String',0 ; 00404010

.code                           ; 代码段
demonstrate_storage proc
    push ebp
    mov ebp, esp
    sub esp, 40h                ; 为局部变量分配栈空间
    
    ; 栈变量:stack_str在[ebp-14h]
    lea eax, [ebp-14h]
    mov byte ptr [eax], 'S'     ; 初始化栈字符串
    
    ; 堆分配调用
    push 32h                    ; 50字节
    call malloc
    add esp, 4
    mov [ebp+heap_str], eax     ; 保存堆指针
    
    ; 访问示例
    mov ecx, offset global_str  ; 全局变量直接地址
    mov edx, [ebp+heap_str]     ; 堆变量通过指针
    lea eax, [ebp-14h]          ; 栈变量通过EBP偏移
    
    mov esp, ebp
    pop ebp
    ret
demonstrate_storage endp

4. 安全与混淆技术

4.1 字符串加密的汇编实现

详细汇编解释:

c 复制代码
#include <windows.h>

// XOR加密函数
void xor_encrypt(char* data, size_t len, char key) {
    for (size_t i = 0; i < len; i++) {
        data[i] ^= key;
    }
}

// 运行时解密
char* decrypt_string(const char* encrypted, size_t len, char key) {
    char* decrypted = malloc(len + 1);
    
    // 内联汇编展示解密过程
    __asm {
        ; === 汇编解释:XOR解密循环 ===
        mov esi, encrypted       ; ESI = 加密数据源
        mov edi, decrypted       ; EDI = 解密目标
        mov ecx, len             ; ECX = 数据长度
        mov dl, key              ; DL = XOR密钥
        
decrypt_loop:
        mov al, [esi]            ; 读取加密字节
        xor al, dl               ; XOR解密:AL = AL ^ DL
        mov [edi], al            ; 存储解密字节
        inc esi                  ; 源指针前进
        inc edi                  ; 目标指针前进
        loop decrypt_loop        ; ECX--,如果≠0继续循环
        
        mov byte ptr [edi], 0    ; 添加字符串终止符
    }
    
    return decrypted;
}

void demonstrate_obfuscation() {
    // 加密的字符串(在IDA中显示为乱码)
    const char encrypted[] = {0x25, 0x2A, 0x2F, 0x2F, 0x2E, 0x00};
    
    char* secret = decrypt_string(encrypted, 5, 0x45);
    
    // 动态获取API(避免导入表暴露)
    HMODULE hUser32 = GetModuleHandleA("user32.dll");
    __asm {
        ; === 汇编解释:动态API解析 ===
        push offset aUser32       ; "user32.dll"
        call GetModuleHandleA
        mov hUser32, eax
        
        push offset aMessageBoxA  ; "MessageBoxA"  
        push eax                  ; user32.dll句柄
        call GetProcAddress       ; 动态获取函数地址
        
        ; 调用动态获取的API
        push 0                    ; uType
        push offset aTitle        ; lpCaption
        push secret               ; lpText
        push 0                    ; hWnd
        call eax                  ; 调用MessageBoxA
    }
    
    free(secret);
}

逆向工程中识别加密字符串:

assembly 复制代码
; 加密字符串在数据段的表现
encrypted_data db 25h, 2Ah, 2Fh, 2Fh, 2Eh, 0  ; 看起来像乱码

; 解密函数的典型模式
decrypt_function:
    mov esi, encrypted_data      ; 加密数据源
    mov edi, buffer              ; 输出缓冲区
    mov ecx, length              ; 数据长度
    mov al, key                  ; 解密密钥
decrypt_loop:
    mov bl, [esi]
    xor bl, al                   ; XOR操作
    mov [edi], bl
    inc esi
    inc edi
    loop decrypt_loop

; 动态API调用的识别
call GetModuleHandleA            ; 获取DLL句柄
push offset api_name             ; API函数名
push eax                         ; DLL句柄
call GetProcAddress              ; 获取函数地址
; 之后通过寄存器或栈间接调用

4.2 安全字符串处理的汇编对比

安全vs不安全实现的汇编对比:

c 复制代码
// 不安全版本
void unsafe_copy(const char* input) {
    char buffer[16];
    strcpy(buffer, input);  // 没有边界检查
}

// 安全版本  
void safe_copy(const char* input) {
    char buffer[16];
    strncpy(buffer, input, sizeof(buffer) - 1);
    buffer[sizeof(buffer) - 1] = '\0';
}

对应的汇编代码对比:

assembly 复制代码
; 不安全版本的汇编
unsafe_copy:
    push ebp
    mov ebp, esp
    sub esp, 10h                ; 分配16字节栈空间
    
    ; 危险的strcpy调用
    push [ebp+8]                ; input参数
    lea eax, [ebp-10h]          ; buffer地址
    push eax
    call strcpy                 ; 没有长度限制!
    add esp, 8
    
    mov esp, ebp
    pop ebp
    ret

; 安全版本的汇编  
safe_copy:
    push ebp
    mov ebp, esp
    sub esp, 10h                ; 分配16字节栈空间
    
    ; 安全的strncpy调用
    push 0Fh                    ; 最大15字符
    push [ebp+8]                ; input参数
    lea eax, [ebp-10h]          ; buffer地址
    push eax
    call strncpy                ; 有长度限制
    add esp, 0Ch
    
    ; 确保终止符
    mov byte ptr [ebp-1], 0     ; buffer[15] = 0
    
    mov esp, ebp
    pop ebp
    ret

逆向工程实战技巧

识别字符串操作的启发式方法

在IDA Pro中的分析模式:

assembly 复制代码
; 模式1:repne scasb - 字符串长度计算
mov edi, [ebp+string_ptr]
xor eax, eax
mov ecx, 0FFFFFFFFh
repne scasb                     ; -> strlen

; 模式2:repe cmpsb - 字符串比较  
mov esi, [ebp+str1]
mov edi, [ebp+str2]
mov ecx, length
repe cmpsb                      ; -> strcmp/memcmp

; 模式3:rep movsb - 字符串复制
mov esi, [ebp+src]
mov edi, [ebp+dst] 
mov ecx, length
rep movsb                       ; -> strcpy/memcpy

; 模式4:手动循环 - 自定义字符串处理
mov esi, [ebp+string]
process_loop:
    mov al, [esi]
    cmp al, 'a'
    jb skip_char
    cmp al, 'z'
    ja skip_char
    sub al, 20h                 ; 小写转大写
    mov [esi], al
skip_char:
    inc esi
    test al, al
    jnz process_loop

字符串混淆的对抗技术

识别和解决字符串混淆:

assembly 复制代码
; 加密字符串的识别特征
encrypted_string db 0A7h, 0C3h, 92h, 15h, 0F4h, 0

; 查找解密循环
mov esi, encrypted_data
mov edi, output_buffer
mov ecx, string_length
mov al, xor_key
decrypt_loop:
    mov bl, [esi]
    xor bl, al                  ; XOR解密
    mov [edi], bl
    inc esi
    inc edi
    loop decrypt_loop

; 动态调试技巧:在解密后设置内存断点
; 1. 找到解密函数
; 2. 在解密完成后(循环结束后)设置内存写入断点
; 3. 运行程序,当明文字符串被使用时触发断点
; 4. 查看明文字符串内容

通过深入理解这些汇编层面的字符串操作模式,逆向工程师可以更有效地分析程序逻辑、定位关键代码、识别安全漏洞,并对抗各种字符串混淆技术。

相关推荐
A9better3 小时前
嵌入式开发学习日志30——stm32之定时器中断简单项目练习
stm32·单片机·嵌入式硬件·学习
充哥单片机设计3 小时前
【STM32项目开源】基于STM32的智能电子秤
stm32·单片机·嵌入式硬件
竹等寒4 小时前
Powershell 管理 后台/计划 作业(六)
服务器·windows·网络安全·powershell
非凡ghost4 小时前
极简时钟APP(手机全能计时工具) 极简版
windows·智能手机·软件需求
学不动CV了6 小时前
C语言(FreeRTOS)中堆内存管理分析Heap_1、Heap_2、Heap_4、Heap_5详细分析与解析(二)
linux·c语言·arm开发·stm32·单片机·51单片机
角砾岩队长6 小时前
Windows系统下的Git安装(2025年6月更新)
windows·git
transuperb14 小时前
51单片机红外遥控
单片机·嵌入式硬件
卓码软件测评15 小时前
第三方软件验收测试:【AutoIt与Selenium结合测试文件上传/下载等Windows对话框】
windows·功能测试·selenium·测试工具·性能优化·可用性测试
Archie_IT18 小时前
嵌入式八股文篇——P1 关键字篇
c语言·开发语言·单片机·mcu·物联网·面试·职场和发展