逆向32位ELF时解引用指令地址指针得0xcc的原因咨询
32位ELF自校验程序调试时读到0xcc值的原因
问题相关汇编代码
08048080 <.text>: 8048080: b8 04 00 00 00 mov eax,0x4 8048085: bb 01 00 00 00 mov ebx,0x1 804808a: b9 a1 91 04 08 mov ecx,0x80491a1 804808f: ba 26 00 00 00 mov edx,0x26 8048094: cd 80 int 0x80 8048096: b8 03 00 00 00 mov eax,0x3 804809b: 31 db xor ebx,ebx 804809d: b9 88 91 04 08 mov ecx,0x8049188 80480a2: ba 33 00 00 00 mov edx,0x33 80480a7: cd 80 int 0x80 80480a9: 31 c9 xor ecx,ecx 80480ab: b8 80 80 04 08 mov eax,0x8048080 80480b0: bb 23 81 04 08 mov ebx,0x8048123 80480b5: e8 5b 00 00 00 call 0x8048115 80480ba: 89 ca mov edx,ecx 80480bc: b9 19 00 00 00 mov ecx,0x19 80480c1: b8 55 91 04 08 mov eax,0x8049155 80480c6: bb 88 91 04 08 mov ebx,0x8049188 80480cb: d1 ca ror edx,1 80480cd: 8a 44 08 ff mov al,BYTE PTR [eax+ecx*1-0x1] 80480d1: 8a 5c 0b ff mov bl,BYTE PTR [ebx+ecx*1-0x1] 80480d5: 30 d8 xor al,bl 80480d7: 30 d0 xor al,dl 80480d9: 75 1b jne 0x80480f6 80480db: 49 dec ecx 80480dc: 75 e3 jne 0x80480c1 80480de: b8 04 00 00 00 mov eax,0x4 80480e3: bb 01 00 00 00 mov ebx,0x1 80480e8: b9 24 91 04 08 mov ecx,0x8049124 80480ed: ba 26 00 00 00 mov edx,0x26 80480f2: cd 80 int 0x80 80480f4: eb 16 jmp 0x804810c 80480f6: b8 04 00 00 00 mov eax,0x4 80480fb: bb 01 00 00 00 mov ebx,0x1 8048100: b9 4a 91 04 08 mov ecx,0x804914a 8048105: ba 0b 00 00 00 mov edx,0xb 804810a: cd 80 int 0x80 804810c: b8 01 00 00 00 mov eax,0x1 8048111: 31 db xor ebx,ebx 8048113: cd 80 int 0x80 8048115: 29 c3 sub ebx,eax 8048117: 31 c9 xor ecx,ecx 8048119: 02 08 add cl,BYTE PTR [eax] 804811b: c1 c1 03 rol ecx,0x3 804811e: 40 inc eax 804811f: 4b dec ebx 8048120: 75 f7 jne 0x8048119 8048122: c3 ret
存在疑问的指令:
8048119: 02 08 add cl,BYTE PTR [eax]
已知进入该指令时EAX存储.text段起始地址,ECX初始值为0,调试时解引用得到的值为0xcc,不符合预期。
指令逻辑与0xcc成因
子函数原生逻辑
0x8048115处的子函数是典型的代码自校验逻辑,设计目的是防止程序代码被篡改:
- 调用前传入两个参数:
eax=0x8048080(.text段起始,校验区域首地址),ebx=0x8048123(校验区域结束地址的后1字节) - 入口
sub ebx,eax计算得到待校验的代码长度为0xA3(163字节),覆盖从.text起始到ret指令(0x8048122)的全部代码 - 循环逻辑:
- 初始化ecx为0,作为校验和存储寄存器
- 逐字节读取待校验区域的内存值,累加到cl(ecx低8位)
- 每次累加后将ecx循环左移3位,完成简单的校验和混淆
- 遍历完所有字节后,ecx存储最终校验值,返回后作为密钥参与后续的输入异或校验:校验和不匹配则直接跳转到错误分支输出失败提示,匹配则输出验证成功信息。
0xcc出现的原因
0xCC是x86架构下int3软中断的操作码,是所有用户态调试器实现软件断点的标准指令。
调试器下软件断点的原理是:临时将目标断点地址的原始指令首字节替换为0xCC,程序执行到该位置时会触发断点异常,被调试器捕获;只有当用户在调试器中下达继续运行的指令时,调试器才会把原始字节写回内存,恢复程序正常执行。
你遇到的情况是:校验逻辑开始执行时,你之前在0x8048080(.text段起始,通常是程序入口点)或者校验区域内其他地址下的软件断点还没被调试器恢复,对应地址的原始字节还被替换为0xCC,所以读取内存时拿到的是断点指令值,而不是程序原始的代码字节。
解决方法
- 删除校验范围(0x8048080~0x8048122)内的所有软件断点,再运行程序就可以得到正确的校验和
- 如果需要调试这段校验逻辑,改用硬件断点:硬件断点依赖CPU的调试寄存器实现,不会修改内存中的原始指令字节,不会干扰自校验计算。
内容的提问来源于stack exchange,提问作者user19415746
相关产品推荐
相关产品推荐

