将汇编 ADC 转换为 C#

逆向工程 艾达 拆卸 C#
2021-07-11 18:08:12

我从可执行文件中获得了这个反汇编的例程,但是我在将其转换为 C# 时遇到了麻烦。

.text:005C9290 ; =============== S U B R O U T I N E =======================================
.text:005C9290
.text:005C9290 ; Attributes: bp-based frame
.text:005C9290
.text:005C9290 sub_5C9290      proc near               ; CODE XREF: .text:00574256p
.text:005C9290                                         ; sub_5ACC50+68p ...
.text:005C9290
.text:005C9290 SystemTimeAsFileTime= _FILETIME ptr -8
.text:005C9290 arg_0           = dword ptr  8
.text:005C9290
.text:005C9290                 push    ebp
.text:005C9291                 mov     ebp, esp
.text:005C9293                 push    ecx
.text:005C9294                 push    ecx
.text:005C9295                 lea     eax, [ebp+SystemTimeAsFileTime]
.text:005C9298                 push    eax             ; lpSystemTimeAsFileTime
.text:005C9299                 call    ds:GetSystemTimeAsFileTime
.text:005C929F                 mov     eax, [ebp+SystemTimeAsFileTime.dwLowDateTime]
.text:005C92A2                 mov     ecx, [ebp+SystemTimeAsFileTime.dwHighDateTime]
.text:005C92A5                 push    0
.text:005C92A7                 add     eax, 2AC18000h
.text:005C92AC                 push    offset unk_989680
.text:005C92B1                 adc     ecx, 0FE624E21h
.text:005C92B7                 push    ecx
.text:005C92B8                 push    eax
.text:005C92B9                 call    sub_5D0500
.text:005C92BE                 mov     ecx, [ebp+arg_0]
.text:005C92C1                 test    ecx, ecx
.text:005C92C3                 jz      short locret_5C92C7
.text:005C92C5                 mov     [ecx], eax
.text:005C92C7
.text:005C92C7 locret_5C92C7:                          ; CODE XREF: sub_5C9290+33j
.text:005C92C7                 leave
.text:005C92C8                 retn
.text:005C92C8 sub_5C9290      endp
.text:005C92C8
.text:005C92C9

但是,我有这个由 IDA Pro 生成的函数的伪代码:

__int64 __cdecl sub_5C9290(int a1)
{
  __int64 result; // qax@1
  unsigned __int64 v2; // ST00_8@1
  struct _FILETIME SystemTimeAsFileTime; // [sp+0h] [bp-8h]@1

  GetSystemTimeAsFileTime(&SystemTimeAsFileTime);
  HIDWORD(v2) = ((_DWORD)SystemTimeAsFileTime.dwLowDateTime >= 0xD53E8000u)
              + SystemTimeAsFileTime.dwHighDateTime
              - 27111903;
  LODWORD(v2) = SystemTimeAsFileTime.dwLowDateTime + 717324288;
  result = sub_5D0500(v2, (unsigned int)&unk_989680, 0);
  if ( a1 )
    *(_DWORD *)a1 = result;
  return result;
}

一个问题是代码不会编译,这段代码没有意义:

HIDWORD(v2) = ((_DWORD)SystemTimeAsFileTime.dwLowDateTime >= 0xD53E8000u)
              + SystemTimeAsFileTime.dwHighDateTime
              - 27111903;

还有一个问题是ADC我能找到命令是它完全一样,ADD但它也将CARRY FLAG结果添加到结果中,但我找不到任何方法在 C# 中重现此命令。那么所有这些HIDWORDLODWORD宏呢?

1个回答

这是 64 位数学。编译器必须分两步进行加法,因为处理器一次只能工作 32 位。并且进位必须从低加法传播到高加法 - 与在纸上进行多位数字相加时的方式相同。

以下是当前版本的反编译器 (1.7) 生成的内容(修复函数原型后):

result = sub5D0500(time - 116444736000000000i64, 10000000i64);

并且(只是猜测)如果您重命名sub5D0500__alldiv(64 位除法的编译器辅助函数),它将变为:

result = (time - 116444736000000000i64) / 10000000;

显然您正在查看 MSVC 的_time64实现。来自time64.c

/*
 * Number of 100 nanosecond units from 1/1/1601 to 1/1/1970
 */
#define EPOCH_BIAS  116444736000000000i64
[...]
__time64_t __cdecl _time64 (
        __time64_t *timeptr
        )
{
        __time64_t tim;
        FT nt_time;
        GetSystemTimeAsFileTime( &(nt_time.ft_struct) );
        tim = (__time64_t)((nt_time.ft_scalar - EPOCH_BIAS) / 10000000i64);
        if (timeptr)
                *timeptr = tim;         /* store time if requested */
        return tim;
}