Mic*_*ott 18 x86 assembly reverse-engineering
我正在尝试对二进制文件进行逆向工程,以下指令让我感到困惑,有人可以澄清这究竟是什么吗?
=>0x804854e:    repnz scas al,BYTE PTR es:[edi]
  0x8048550:    not    ecx
哪里:
EAX: 0x0
ECX: 0xffffffff
EDI: 0xbffff3dc ("aaaaaa\n")
ZF:  1
我看到它在某种程度上以每次迭代递减1次ECX,并且EDI沿着字符串的长度递增.我知道它会计算字符串的长度,但至于它是如何发生的,以及为什么"al"涉及到我不太确定.
Qua*_*key 28
我将尝试通过将代码反转回C来解释它.
英特尔的指令集参考(软件开发人员手册的第2卷)对于这种逆向工程非常有用.
REPNE和SCASB的逻辑相结合:
while (ecx != 0) {
    temp = al - *(BYTE *)edi;
    SetStatusFlags(temp);
    if (DF == 0)   // DF = Direction Flag
        edi = edi + 1;
    else
        edi = edi - 1;
    ecx = ecx - 1;
    if (ZF == 1) break;
}
或者更简单:
while (ecx != 0) {
    ZF = (al == *(BYTE *)edi);
    if (DF == 0)
        edi++;
    else
        edi--;
    ecx--;
    if (ZF) break;
}
但是,上述内容不足以解释它如何计算字符串的长度.根据not ecx您问题中的存在,我假设该片段属于此成语(或类似),用于计算字符串长度REPNE SCASB:
sub ecx, ecx
sub al, al
not ecx
cld
repne scasb
not ecx
dec ecx
转换为C并使用上一节中的逻辑,我们得到:
ecx = (unsigned)-1;
al = 0;
DF = 0;
while (ecx != 0) {
    ZF = (al == *(BYTE *)edi);
    if (DF == 0)
        edi++;
    else
        edi--;
    ecx--;
    if (ZF) break;
}
ecx = ~ecx;
ecx--;
简化使用al = 0和DF = 0:
ecx = (unsigned)-1;
while (ecx != 0) {
    ZF = (0 == *(BYTE *)edi);
    edi++;
    ecx--;
    if (ZF) break;
}
ecx = ~ecx;
ecx--;
注意事项:
ecx相当于-1 - ecx.ecx在循环中断之前递减,因此它length(edi) + 1总计减少.ecx 循环中永远不能为零,因为字符串必须占用整个地址空间.所以在上面的循环之后,ecx包含-1 - (length(edi) + 1)哪个是相同的-(length(edi) + 2),我们将这些位翻转给予length(edi) + 1,最后递减给出length(edi).
或者重新排列循环并简化:
const char *s = edi;
size_t c = (size_t)-1;      // c == -1
while (*s++ != '\0') c--;   // c == -1 - length(s)
c = ~c;                     // c == length(s)
并反转计数:
size_t c = 0;
while (*s++ != '\0') c++;
这是strlenC 的功能:
size_t strlen(const char *s) {
    size_t c = 0;
    while (*s++ != '\0') c++;
    return c;
}
Jes*_*ter 17
AL涉及,因为scas扫描内存的值AL.AL已被归零,以便指令在字符串的末尾找到终止零.scas自动递增(或递减,取决于方向标志)EDI.的REPNZ前缀(这是在更可读的REPNE形式)重复scas只要比较结果为假(REP吃而Ñ OT È QUAL)和ECX > 0.它也会ECX在每次迭代中自动递减.ECX已被初始化为最长的字符串,因此它不会提前终止循环.
由于ECX从0xffffffff(也称为-1)向下计数,因此-1-ECX可以使用NOT指令计算由于2的补码运算的特性而导致的结果长度.