首页
社区
课程
招聘
[原创]Practical Reverse Engineering Exercise P11 Write-up
2023-7-24 14:31 3888

[原创]Practical Reverse Engineering Exercise P11 Write-up

2023-7-24 14:31
3888

Practical Reverse Engineering Exercise P11

1
2
3
4
5
6
7
8
9
10
11
01: 8B 7D 08 mov edi, [ebp+8]
02: 8B D7 mov edx, edi
03: 33 C0 xor eax, eax
04: 83 C9 FF or ecx, 0FFFFFFFFh
05: F2 AE repne scasb
06: 83 C1 02 add ecx, 2
07: F7 D9 neg ecx
08: 8A 45 0C mov al, [ebp+0Ch]
09: 8B FA mov edi, edx
10: F3 AA rep stosb
11: 8B C2 mov eax, edx

先贴出这个练习的代码。主要考察的是 scasstos指令的用法。首先根据[ebp+8]和[ebp+0ch]可以判断出这应该是一个被调用函数的实现代码,但这对于我们分析这段代码没关系。下面对每行代码进行分析。

  • Line 1 mov edi, [ebp+8]

    取地址为 ebp+8 的 double word 存入 edi 中。若此代码段为被调用函数,则此条语句为取第一个参数到 edi。现在看不出来这个 double word 到底是什么。

  • Line 2 mov edx, edi

    把 edi 的值复制到 edx 中。

  • Line 3 xor eax, eax

    将 eax 置零。

  • Line 4 or ecx, 0FFFFFFFFh

    设置 ecx = -1,做什么用处现在还看不出来。

  • Line 5 repne scasb

    这是最关键的一步。首先看 scas指令,它进行如下操作:

    • 将 edi 指向的地址与 al/ax/eax 比较,具体长度由后缀决定,如 scasb, scasw, scasd 分别对应 1-,2-,4- 字节。同时,edi 自增相应长度(这里有个需要注意的是 esi 未必一定是自增的,其自增和自减与否有 DF 寄存器的值决定)。
    • ecx = ecx - 1

    由于以上特性,所以此指令经常与 REP 指令一起出现,例如此条指令就是将 edi 指向的 double word 与 eax 比较,如果不等,则 edi = edi + 4, 直到相等。

  • Line 6 add ecx, 2

  • Line 7 neg ecx

    之所以把这俩放到一起,是因为单看第六行指令很难理解,所以就继续往下看,发现对 ecx 取相反数了。首先由第五行的 scasd 指令可知 ecx 的值从 -1 又减小了从开始字符到遇到第一个 \0 时的长度。所以可以猜测这段代码用来计算字符串长度。

    所以,如果 edi 指向的字符串为 \0,则 ecx 完成第五行指令后的值为 -2。则完成第六行和第七行指令后的值分别为 0, 0。同理,如果 edi 指向的字符串为 hello\0,则上述值分别为 -7, -5, 5

    故,此时 ecx 内存放的是此字符串的长度。

  • Line 8 mov al, [ebp+0Ch]

    将地址为 ebp+0Ch 的 byte 存入 al 中。若此代码段为被调用函数,则此条语句为取第二个参数到 al。

  • Line 9 mov edi, edx

    这里将第二行存入 edx 的值取出来,即将 edi 恢复成字符串头地址。

  • Line 10 rep stosb

    继续先看 stos指令,它进行如下操作:

    • 根据具体指令,如 stosb, stosw, stosd 分别将 al, ax, eax 的值写入到 edi 所指向的位置, edi 同样根据 DF 寄存器的值自增/自减相应长度。
    • ecx = ecx - 1

    所以这条指令就是把从字符串头开始位置,长度为 ecx(从第七行可知 ecx 为字符串长度)的内存块写入寄存器 al 的值。相当于 memset()。

  • Line 11 mov eax, edx

    将字符串首地址作为返回值返回。

这段代码的 C 语言表示为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
char* replace_with_x(char *des, char x) {
    int count = -1;
    char *ret = des;
    while (*des != '\0') {
        count -= 1;
        des += 1;
    }
    count += 2;
    count = -count;
    des = ret;
    while (count != 0) {
        *des = x;
        des += 1;
        count -= 1;
    }
    return ret;
}

[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法

收藏
点赞2
打赏
分享
最新回复 (2)
雪    币: 295
活跃值: (108)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
phoenixli 2023-7-29 17:16
2
0
讲解很详细,对反汇编代码的理解很有帮助,很希望能多看到这类文章。
雪    币: 19461
活跃值: (29125)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
秋狝 2023-7-29 23:24
3
1
感谢分享
游客
登录 | 注册 方可回帖
返回