IDA反编译中_time64传0而非NULL且返回int32的原因咨询
关于
_time64()参数与返回值的疑问解答 分析场景与问题
我正在分析IDA反编译的代码,重点关注now_int = time64(0);这一行。根据微软文档,_time64()应接受指针或NULL,返回__time64_t类型,但反编译代码中传入参数0,返回的UNIX时间戳被存储为int32类型。相关代码信息如下:
反编译代码
int unknown_seed_stuff() { int now_int; // eax double now_double; // xmm0_8 now_int = time64(0); srand(now_int); now_double = (double)time64(0); if ( now_double >= 2147483647.0 ) now_double = now_double * 0.5; prng_seed_0 = now_double; dword_FF9268 = time64(0) ^ 0xC; return atexit(nullsub_141); }
汇编代码
.text:00413CB0 unknown_seed_stuff proc near ; DATA XREF: .rdata:00D263D0↓o .text:00413CB0 push esi .text:00413CB1 mov esi, ds:_time64 .text:00413CB7 push 0 ; Time .text:00413CB9 call esi ; _time64 .text:00413CBB push eax ; Seed .text:00413CBC call ds:srand .text:00413CC2 push 0 ; Time .text:00413CC4 call esi ; _time64 .text:00413CC6 add esp, 0Ch .text:00413CC9 mov ecx, eax .text:00413CCB call __ltod3 .text:00413CD0 comisd xmm0, ds:MAXINT .text:00413CD8 jb short loc_413CE2 .text:00413CDA mulsd xmm0, ds:qword_E69F70 .text:00413CE2 .text:00413CE2 loc_413CE2: ; CODE XREF: unknown_seed_stuff+28↑j .text:00413CE2 push 0 ; Time .text:00413CE4 movsd prng_seed_0, xmm0 .text:00413CEC call esi ; _time64 .text:00413CEE xor eax, 0Ch .text:00413CF1 push offset nullsub_141 ; void (__cdecl *)() .text:00413CF6 mov dword_FF9268, eax .text:00413CFB call _atexit .text:00413D00 add esp, 8 .text:00413D03 pop esi .text:00413D04 retn .text:00413D04 unknown_seed_stuff endp
导入表信息
.idata:00D25410 ; __time64_t (__cdecl *time64)(__time64_t *Time) .idata:00D25410 _time64 dd offset msvcr120__time64 .idata:00D25410 ; CODE XREF: unknown_seed_stuff+9↑p .idata:00D25410 ; unknown_seed_stuff+14↑p ...
疑问:为何_time64()接受参数0而非指针或NULL,且返回值不是__time64_t类型而是int32的时间戳?
解答
1. 参数0与NULL的等价性
在C/C++中,NULL本质是值为0的指针(32位环境下为(void*)0)。反编译代码里的0和NULL在底层汇编层面完全等价——汇编代码中明确是push 0作为参数传递,这和传入NULL的行为没有任何区别,只是IDA反编译时选择用数值0来表示空指针,而非宏NULL。
2. 返回值存储为int32的原因
从导入表可知程序确实调用了msvcr120__time64,其返回值为64位的__time64_t,但这里是32位程序:
- 32位环境下,
_time64的64位返回值会被拆分到edx:eax寄存器对(高32位在edx,低32位在eax),但反编译代码只取了eax部分(低32位时间戳),并存入int类型变量。 - 代码后续逻辑也验证了这一点:将时间转为
double后,判断是否大于等于2147483647.0(int32的最大值),若超过则乘以0.5——这说明代码故意只使用时间戳的低32位,甚至做了溢出兼容处理,是代码本身的逻辑选择,而非_time64返回了32位值。
简言之:IDA反编译用0替代了NULL,而代码主动截取了_time64返回值的低32位存储,并非函数返回值类型错误。
内容的提问来源于stack exchange,提问作者Daniel
相关产品推荐
相关产品推荐

