在转换期间,我遇到了一个无法找到任何答案的问题。
因此,这是它:
...
+---->6C250EAD MOV DL, BYTE PTR DS:[ESI]
| .....EAF TEST DL, DL
| .....EB1 JE SHORT func.6C250EDF -----------------+
| .....EB3 MOVZX EDX, DL |
| .....EB6 TEST BYTE PTR DS:[EDX+0x6C25EF39],0x4 |
| .....EBD JE SHORT func.6C250ECE -----+ |
| .....EBF ADD DWORD PRT DS:[ECX],0x2 | |
| .....EC2 TEST EAX,EAX | |
| .....EC4 JE SHORT func.6C250ED9 ----------+ |
| .....EC6 MOV DL, BYTE PTR DS:[ESI] | | |
| .....EC8 INC ESI | | |
| .....EC9 MOV BYTE PTR DS:[EAX], DL | | |
| .....ECB INC EAX | | |
| +--.....ECC-----JMP SHORT func.6C250ED4 | | |
| | 6C250ECE INC DWORD PTR DS:[ECX]<<<<<<--+ | |
| | .....ED0 TEST EAX, EAX | |
| | .....ED2 JMP SHORT func.6C250ED9 -----------+ |
| +->6C250ED4 MOV DL, BYTE PTR DS:[ESI] | | |
| .....ED6 MOV BYTE PTR DS:[EAX],DL | | |
| .....ED8 INC EAX | | |
| 6C250ED9 INC ESI <<<<<-----------------+--+ |
| .....EDA CMP BYTE PTR DS:[ESI],0x22 |
+-----.....EDD-----JNZ SHORT func.6C250EAD |
6C250EDF ..... <<<<------------------------------+
首先,我必须说我们在寄存器ESI中存储了一个字符串。特别是,这是我尝试检查的当前过程的路径。因此,它以“ C:\ Users ...(依此类推)”开头。
我的观察如下。这是一个代表循环的例程。循环通过在循环末尾增加esi指针来遍历存储的字符串。还有一个递增的计数器ECX。
我的问题是关于这行的:
TEST BYTE PTR DS:[EDX+0x6C25EF39],0x4
在这里,ollydbg宣布我在[EDX + 0x6C25EF39]中输入了ANSCII代码08。我查了一下,这就是退格的代码。此外,0x4是EOT(=传输结束)的表示。
老实说,我真的不明白这是什么。 (我认为可能是删除最后一个当前字符,因为它不是“传输结束”,即0x4,但我不确定。)我唯一可以说的是结果始终为ZF = 1,因此进行跳转,然后我们转到箭头的目标,即计数器ECX递增的位置。
关于ECX和EAX,我可以说它们是用0初始化的。
因此,从这些观察中,我尝试编写一个C代码以想象如何真正地编写它:
while(esi != NULL){
char *dl = *(esi);
if(dl != dl){
break;
}
char *edx = *(dl);
//at that the line which I do not understand really comes
ecx++;
if(eax!=0){
esi++;
}
if(esi-- == esi){
break;
}
}
我想补充一点,也尝试学习C语言。因此,我希望您能告诉我我的错误或其他错误的事情,我必须更好地学习。
#1 楼
请注意,我将代码从6C250ED4-6C250ED8移到.... ECC,以使if / else更加清晰。6C250EAD MOV DL, BYTE PTR DS:[ESI] | while (dl = *esi) {
TEST DL, DL |
JE SHORT 6C250EDF |
MOVZX EDX, DL |
TEST BYTE PTR DS:[EDX+0x6C25EF39],0x4 | if (charinfo[dl]&4) {
JE SHORT 6C250ECE |
ADD DWORD PRT DS:[ECX],0x2 | *ecx += 2
TEST EAX,EAX | if (eax) {
JE SHORT 6C250ED9 |
MOV DL, BYTE PTR DS:[ESI] | *eax++ = *esi++
INC ESI |
MOV BYTE PTR DS:[EAX], DL |
INC EAX |
MOV DL, BYTE PTR DS:[ESI] | *eax++ = *esi
MOV BYTE PTR DS:[EAX],DL |
INC EAX | }
JMP SHORT 6C250ED9 | } else {
6C250ECE INC DWORD PTR DS:[ECX] | *ecx += 1
TEST EAX, EAX | // ignored
JMP SHORT 6C250ED9 | }
6C250ED9 INC ESI |
CMP BYTE PTR DS:[ESI],0x22 | } while (*++esi!='"')
JNZ SHORT 6C250EAD |
charinfo表可能类似于isspace()或isalnum(),来自ctype.h
#2 楼
// +---->6C250EAD MOV DL, BYTE PTR DS:[ESI]
// | .....EAF TEST DL, DL
// | .....EB1 JE SHORT func.6C250EDF -----------------+
// | .....EB3 MOVZX EDX, DL |
// | .....EB6 TEST BYTE PTR DS:[EDX+0x6C25EF39],0x4 |
// | .....EBD JE SHORT func.6C250ECE -----+ |
// | .....EBF ADD DWORD PRT DS:[ECX],0x2 | |
// | .....EC2 TEST EAX,EAX | |
// | .....EC4 JE SHORT func.6C250ED9 ----------+ |
// | .....EC6 MOV DL, BYTE PTR DS:[ESI] | | |
// | .....EC8 INC ESI | | |
// | .....EC9 MOV BYTE PTR DS:[EAX], DL | | |
// | .....ECB INC EAX | | |
// | +--.....ECC-----JMP SHORT func.6C250ED4 | | |
// | | 6C250ECE INC DWORD PTR DS:[ECX]<<<<<<--+ | |
// | | .....ED0 TEST EAX, EAX | |
// | | .....ED2 JMP SHORT func.6C250ED9 -----------+ |
// | +->6C250ED4 MOV DL, BYTE PTR DS:[ESI] | | |
// | .....ED6 MOV BYTE PTR DS:[EAX],DL | | |
// | .....ED8 INC EAX | | |
// | 6C250ED9 INC ESI <<<<<-----------------+--+ |
// | .....EDA CMP BYTE PTR DS:[ESI],0x22 |
// +-----.....EDD-----JNZ SHORT func.6C250EAD |
// 6C250EDF ..... <<<<------------------------------+
while (*ESI!=0) {
DL=(char)*ESI;
if ((some_table_of_chars[DL]&4)!=0) { /* lengthy, but explicit */
*ECX=*ECX+1; /* 4 byte integer */
} else {
*ECX=*ECX+2; /* 4 byte integer */
if (EAX!=0) { /* don't write to NULL address */
DL=(char)*ESI;
(char)*EAX=DL;
ESI++;
EAX++;
DL=(char)*ESI;
(char)*EAX=DL;
EAX++;
}
}
ESI++;
if (*ESI=='"') {
break;
}
}
我几乎猜到它是将字符从
[ESI]
复制到[EAX]
,也许这样做是在计算单宽度或双倍宽度字符,停在字符串的任一端([ESI]
)或双引号。评论
TEST ...,0x4是按位与,而不是相等检查。还是+1,因为您击败了我才能发布答案:)
– DCoder
2014年5月27日下午5:15
h!你是对的!因此,我们正在检查一个标志...。我将更新...
– lornix
2014年5月27日下午5:16
几乎就像它使用该标志来确定是跳过该字符还是复制两个字符。疯狂的Windows及其UTF16怪异。
– lornix
2014年5月27日下午5:25
#3 楼
如果无法在某些示例数据中看到它的作用(或至少在6C25EF39上为256个字节),您将无法确定类似的内容,但是我想说,此例程将计算utf-8的长度字符串并可选地复制它。ESI
是指向原始字符串的指针,EAX
是指向目标的指针,但也可能为零,并且ECX
是指向字符串长度的指针。0x6C25EF39处的表将是一个256字节的表,使用ascii代码作为索引,每个字节有一些标志来定义字符的属性。像这样:
#define UTF8_2BYTE 0x04
unsigned char flags[256]={ .... }
#define IS_UTF8_2BYTEMARK(x) (flags[(x)] & UTF8_2BYTE)
.... // char *esi=source, char *eax=dest, int *ecx=length
for ( ; *esi != '"'; esi++) {
dl=*esi; // ...EAD
if (dl=='q4312078q')
break;
if (IS_UTF8_2BYTEMARK(dl)) { // ...EB6
*ecx+=2;
if (!eax) // ...EC2
continue;
*eax++=*esi++; // ...EC6..ECB
} else {
*ecx++; // ...ECE
}
if (eax)
*eax++=*esi; // ...ED4
}
循环的“ esi ++”部分位于6C250ED9,这是“ continue”跳转到的位置。
在我的for循环中,
*esi != '"'
是前提条件;它不在您的代码中,但我希望它位于您的循环之前。
评论
请给我们提供带有地址的程序集清单吗?该示例中有几个循环可以提供帮助。