You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

x86汇编栈内密钥乱码问题:如何提取可读字符串?

分析与解决:从x86汇编栈中提取128位可读密钥

首先直接点出你的核心误区:你提前在pop esi后断下,既没考虑x86的小端序存储特性,也没等程序执行完XOR解密循环,所以看到的是加密且字节序反转的乱码——你的初始思路方向没错,但断点时机和细节没把握对。

乱码的两大原因

1. x86小端序导致字节顺序反转

x86架构是小端序存储:多字节数据的低字节存在低地址,高字节存在高地址。你看到的每个push dword 0xXXXXXXX,实际压入栈的字节顺序是反过来的。比如push dword 0x76767975,拆成单个字节是0x75('u')、0x79('y')、0x76('v')、0x76('v'),栈里实际存储的是u y v v,而不是直接把0x76767975转成字符串。所有push的dword都要反转字节顺序才能得到加密后的原始字节序列。

2. 未执行解密逻辑就断点

看你的汇编源码,pop esi之后的代码是关键解密流程:

mov edi,esi
mov edx,edi
cld
mov ecx,0x80  ; 要处理128字节
mov ebx,0x41  ; 解密密钥是0x41(ASCII 'A')
xor eax,eax
push eax
lodsb         ; 从esi取一个字节到eax
xor eax,ebx   ; 字节异或0x41解密
stosb         ; 把解密后的字节存回edi(和esi同地址,原地解密)
jnz 0xb7      ; 循环处理完所有128字节

你在pop esi后就断下,这时候程序还没开始解密,栈里全是加密后的原始数据,自然是乱码。

调整流程提取可读字符串的两种方法

方法1:让程序执行完解密循环再断点

最简单的方式是把断点设在解密完成后的位置——也就是汇编里的int3指令处(从你的代码看,这个指令在循环结束后)。

  1. 先找到int3的实际地址,用GDB查看:
    x/1i 0x565560b7+0x10  # 或者直接搜索int3指令
    
  2. 设置断点并运行:
    break *<int3的实际地址>
    r
    
  3. 程序停在int3时,栈里的内容已经完成解密,直接用x/32s $esp(或者按你需要的长度)查看,就能得到可读的密钥字符串。

方法2:手动解密原始栈数据

如果你不想让程序执行到解密完成,也可以手动计算:

  1. 反转每个push的dword字节顺序:把所有push dword 0xXXXXXXX的十六进制值,按字节反转(比如0x76767975 → 0x75797676),然后转成ASCII字符,拼接成加密后的完整字符串。
  2. 逐字节异或0x41:把加密后的每个字符的ASCII值,和0x41(十进制65)做异或运算。比如加密字符#(ASCII 35),35 ^ 65 = 100 → 对应字符d;加密字符'(ASCII 39),39 ^ 65 = 96 → 对应字符`,以此类推处理所有字节,就能得到解密后的可读密钥。

内容的提问来源于stack exchange,提问作者3therk1ll

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 09:23:52