Intel x86汇编验证密码的字符串索引计算方法问询
汇编逆向中验证密码的索引计算解析
基础信息
我是汇编语言初学者,正在用IDA分析Intel x86程序的逆向工程。目标程序通过生成验证密码,与用户输入对比完成验证,匹配则通过:
- 验证密码由16次循环生成,字符来自
CHARACTERS标签指向的字符串:ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890 var_40的十六进制值为-40(即0xFFFFFFC0)
核心问题
看不懂循环中字符串索引的计算逻辑:已知字符取自CHARACTERS地址 + [ebp+ecx*4+var_40]的偏移,但不知道如何通过这个内存地址表达式确定每次循环的索引数值。
相关汇编代码
验证密码生成循环
mov [ebp+loop_counter], 0 loc_8049201: cmp [ebp+loop_counter], 0Fh ; 比较循环计数器与15(0Fh) jge loc_804922F ; 计数器≥15时跳出循环 mov eax, CHARACTERS ; 加载字符集地址到eax mov ecx, [ebp+loop_counter] ; ecx = 当前循环计数器(0~15) mov ecx, [ebp+ecx*4+var_40] ; ecx = 从栈数组中取对应下标的32位整数 mov dl, [eax+ecx] ; 从字符集取第ecx个字符到dl mov eax, [ebp+loop_counter] mov [ebp+eax+validation_password], dl ; 将字符存入验证密码对应位置 mov eax, [ebp+loop_counter] add eax, 1 ; 计数器+1 mov [ebp+loop_counter], eax jmp loc_8049201 ; 跳回循环开头 loc_804922F: lea eax, [ebp+validation_password] ; 加载验证密码地址 mov ecx, [ebp+user_password] mov edx, esp mov [edx+4], ecx mov [edx], eax call _strcmp ; 调用strcmp对比两个密码 cmp eax, 0 ; 对比结果是否为0(匹配) jnz loc_804925D ; 不匹配则跳转
栈数组初始化代码
ebp+var_40指向的栈数组通过_memcpy初始化:
push ebp mov ebp, esp push esi sub esp, 64h mov eax, [ebp+user_password] xor ecx, ecx lea edx, unk_804A064 ; 源数据起始地址,第一个字节为0x3 lea esi, [ebp+var_40] ; 目标地址:栈上ebp-0x40的位置 mov [esp], esi mov [esp+4], edx mov dword ptr [esp+8], 3Ch ; 复制长度60字节(0x3C) mov [ebp+var_58], eax mov [ebp+var_5C], ecx call _memcpy
补充数据
unk_804A064起始的60字节按小端序整理为32位整数(每个整数占4字节):
- 下标0:
0x00000003 - 下标1:
0x00000034 - 下标2:
0x00000038 - 下标3:
0x0000001A - 下标4:
0x0000002C - 下标5:
0x0000002C - 下标6:
0x0000001E - 下标7:
0x00000026 - 下标8:
0x0000001B - 下标9:
0x00000025 - 下标10:
0x00000032 - 下标11:
0x00000013 - 下标12:
0x00000037 - 下标13:
0x0000002C - 下标14:
0x0000000A
索引计算逻辑拆解
- 地址转换:
ebp+var_40等价于ebp-0x40,这是栈上一个数组的起始地址,通过memcpy复制了60字节(15个32位整数)。 - 下标取值:
[ebp+ecx*4+var_40]的含义是:以当前循环计数器ecx为数组下标,取该数组中第ecx个32位整数(每个整数占4字节,所以乘4)。这个整数就是字符集的索引偏移。 - 字符获取:用这个偏移值加上
CHARACTERS的地址,取出对应位置的字符,存入验证密码的对应位置。
验证密码生成结果(基于现有数据)
按循环计数器014,对应字符如下(字符集下标从0开始:025为大写字母,2651为小写字母,5261为数字):
- 计数器0 → 偏移0x3 →
D - 计数器1 → 偏移0x34(52) →
0 - 计数器2 → 偏移0x38(56) →
4 - 计数器3 → 偏移0x1A(26) →
a - 计数器4 → 偏移0x2C(44) →
r - 计数器5 → 偏移0x2C(44) →
r - 计数器6 → 偏移0x1E(30) →
e - 计数器7 → 偏移0x26(38) →
i - 计数器8 → 偏移0x1B(27) →
b - 计数器9 → 偏移0x25(37) →
h - 计数器10 → 偏移0x32(50) →
y - 计数器11 → 偏移0x13(19) →
T - 计数器12 → 偏移0x37(55) →
3 - 计数器13 → 偏移0x2C(44) →
r - 计数器14 → 偏移0x0A(10) →
K
注:循环共16次,现有数据仅覆盖前15次,第16次的索引需查看栈上对应位置的数值。
内容的提问来源于stack exchange,提问作者TasH
相关产品推荐
相关产品推荐

