我有以下汇编代码,我想将其转换为C语言。
在转换期间,我遇到了一个无法找到任何答案的问题。

因此,这是它:

                     ...
  +---->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 != '"'是前提条件;它不在您的代码中,但我希望它位于您的循环之前。