Assembly 如何简化将自身引用为参数的函数?(这意味着什么)
我经常遇到调用自身的函数(在IDA生成的伪代码中),例如:Assembly 如何简化将自身引用为参数的函数?(这意味着什么),assembly,x86-64,reverse-engineering,disassembly,ida,Assembly,X86 64,Reverse Engineering,Disassembly,Ida,我经常遇到调用自身的函数(在IDA生成的伪代码中),例如: 由于反汇编是调用qword ptr[rax],这不能简化为result=lambda()someFunction(a); 当出现诸如lambda+8i64(即call qword ptr[rax+8])之类的调用时,会发生什么情况 类似地,vftable中可能有多个函数,+仅获取其他函数的地址 假设64位函数指针,+8将是表中的第二个函数 另请参见:更多信息另请参见:可能重复 .text:0000000180005F70 ; __in
调用qword ptr[rax]
,这不能简化为result=lambda()如果我用c翻译伪代码
lambda+8i64
(即call qword ptr[rax+8]
)之类的调用时,会发生什么情况__int64 __fastcall CR_maybeParseWithLambda(_QWORD *a1, __int64 newPtr, __int64 positionOrCounter)
{
volatile signed __int32 *lambda; // rdi
__int64 result; // rax
lambda = (volatile signed __int32 *)a1[1];
if ( lambda )
{
result = (unsigned int)_InterlockedExchangeAdd(lambda + 2, 0xFFFFFFFF);
if ( (_DWORD)result == 1 )
{
result = (**(__int64 (__fastcall ***)(volatile signed __int32 *))lambda)(lambda);
if ( _InterlockedExchangeAdd(lambda + 3, 0xFFFFFFFF) == 1 )
result = (*(__int64 (__fastcall **)(volatile signed __int32 *))(*(_QWORD *)lambda + 8i64))(lambda);
a1[1] = positionOrCounter;
*a1 = newPtr;
}
else
{
a1[1] = positionOrCounter;
*a1 = newPtr;
}
}
else
{
a1[1] = positionOrCounter;
*a1 = newPtr;
}
return result;
}
拆解,也来自IDA:
.text:0000000180005F70 ; __int64 __fastcall CR_maybeParseWithLambda(_QWORD *a1, __int64 newPtr, __int64 positionOrCounter)
.text:0000000180005F70 CR_maybeParseWithLambda proc near ; CODE XREF: sub_180005B10+10F↑p
.text:0000000180005F70 ; sub_180005B10+14A↑p ...
.text:0000000180005F70
.text:0000000180005F70 arg_0 = qword ptr 8
.text:0000000180005F70 arg_8 = qword ptr 10h
.text:0000000180005F70 arg_10 = qword ptr 18h
.text:0000000180005F70 arg_18 = qword ptr 20h
.text:0000000180005F70
.text:0000000180005F70 mov [rsp+arg_8], rbx
.text:0000000180005F75 mov [rsp+arg_10], rbp
.text:0000000180005F7A mov [rsp+arg_18], rsi
.text:0000000180005F7F push rdi
.text:0000000180005F80 sub rsp, 20h
.text:0000000180005F84 mov rdi, [rcx+8]
.text:0000000180005F88 mov rsi, r8
.text:0000000180005F8B mov rbp, rdx
.text:0000000180005F8E mov rbx, rcx
.text:0000000180005F91 test rdi, rdi
.text:0000000180005F94 jz short loc_180005FF3
.text:0000000180005F96
.text:0000000180005F96 loc_180005F96: ; DATA XREF: .rdata:0000000180401E74↓o
.text:0000000180005F96 ; .rdata:0000000180401E84↓o ...
.text:0000000180005F96 mov [rsp+28h+arg_0], r14
.text:0000000180005F9B or r14d, 0FFFFFFFFh
.text:0000000180005F9F mov eax, r14d
.text:0000000180005FA2 lock xadd [rdi+8], eax
.text:0000000180005FA7 cmp eax, 1
.text:0000000180005FAA jnz short loc_180005FEA
.text:0000000180005FAC mov rax, [rdi]
.text:0000000180005FAF mov rcx, rdi
.text:0000000180005FB2 call qword ptr [rax]
.text:0000000180005FB4 lock xadd [rdi+0Ch], r14d
.text:0000000180005FBA cmp r14d, 1
.text:0000000180005FBE jnz short loc_180005FC9
.text:0000000180005FC0 mov rax, [rdi]
.text:0000000180005FC3 mov rcx, rdi
.text:0000000180005FC6 call qword ptr [rax+8]
.text:0000000180005FC9
.text:0000000180005FC9 loc_180005FC9: ; CODE XREF: CR_maybeParseWithLambda+4E↑j
.text:0000000180005FC9 mov [rbx+8], rsi
.text:0000000180005FCD mov [rbx], rbp
.text:0000000180005FD0
.text:0000000180005FD0 loc_180005FD0: ; CODE XREF: CR_maybeParseWithLambda+81↓j
.text:0000000180005FD0 mov r14, [rsp+28h+arg_0]
.text:0000000180005FD5
.text:0000000180005FD5 loc_180005FD5: ; CODE XREF: CR_maybeParseWithLambda+8A↓j
.text:0000000180005FD5 ; DATA XREF: .pdata:0000000180483888↓o ...
.text:0000000180005FD5 mov rbx, [rsp+28h+arg_8]
.text:0000000180005FDA mov rbp, [rsp+28h+arg_10]
.text:0000000180005FDF mov rsi, [rsp+28h+arg_18]
.text:0000000180005FE4 add rsp, 20h
.text:0000000180005FE8 pop rdi
.text:0000000180005FE9 retn
调用qword ptr[rax]
,这不能简化为result=lambda()如果我用c翻译伪代码
void f()
您可以更改lambda
的类型以避免这种情况
为什么在伪代码中函数将自身作为参数
仔细阅读汇编代码和反编译代码lambda
不是函数指针,要从中获取函数指针,必须取消引用两次。所以它可能是这样的(伪C++代码)
使用FunctionType=int(int);
结构B{
函数类型*函数指针;
};
结构A{
B*B;
};
A*lambda;//根据这种解释,变量名有点误导。
自动函数指针=(*(*lambda).b);
函数指针(λ);
考虑到双解引用,很可能B
实际上是a(尽管在这些情况下,通常使用\uu thiscall
约定调用函数)——因此代码可以这样编写:
struct Base{
虚拟函数(){}
虚拟void otherFunction(){}
};
已生成结构基\u vftableType{//编译器
void(*someFunction)(Base*);//显示显式(this)参数
void(*otherFunction)(Base*);//显示显式(this)参数
};
派生结构:基{
Base_vftableType*vftable;//编译器生成
void someFunction(){/*…*/}
};
基\u vftableType派生的\u vftable{/*…*/};//编译器生成的vftable
导出*a;
//在pseudo-C中,函数调用与此类似
//(以及它将如何在IDA中显示):
a->vftable->someFunction(a);
当出现诸如lambda+8i64
(即call qword ptr[rax+8]
)之类的调用时,会发生什么情况
类似地,vftable中可能有多个函数,+
仅获取其他函数的地址
假设64位函数指针,+8
将是表中的第二个函数
另请参见:更多信息另请参见:可能重复
.text:0000000180005F70 ; __int64 __fastcall CR_maybeParseWithLambda(_QWORD *a1, __int64 newPtr, __int64 positionOrCounter)
.text:0000000180005F70 CR_maybeParseWithLambda proc near ; CODE XREF: sub_180005B10+10F↑p
.text:0000000180005F70 ; sub_180005B10+14A↑p ...
.text:0000000180005F70
.text:0000000180005F70 arg_0 = qword ptr 8
.text:0000000180005F70 arg_8 = qword ptr 10h
.text:0000000180005F70 arg_10 = qword ptr 18h
.text:0000000180005F70 arg_18 = qword ptr 20h
.text:0000000180005F70
.text:0000000180005F70 mov [rsp+arg_8], rbx
.text:0000000180005F75 mov [rsp+arg_10], rbp
.text:0000000180005F7A mov [rsp+arg_18], rsi
.text:0000000180005F7F push rdi
.text:0000000180005F80 sub rsp, 20h
.text:0000000180005F84 mov rdi, [rcx+8]
.text:0000000180005F88 mov rsi, r8
.text:0000000180005F8B mov rbp, rdx
.text:0000000180005F8E mov rbx, rcx
.text:0000000180005F91 test rdi, rdi
.text:0000000180005F94 jz short loc_180005FF3
.text:0000000180005F96
.text:0000000180005F96 loc_180005F96: ; DATA XREF: .rdata:0000000180401E74↓o
.text:0000000180005F96 ; .rdata:0000000180401E84↓o ...
.text:0000000180005F96 mov [rsp+28h+arg_0], r14
.text:0000000180005F9B or r14d, 0FFFFFFFFh
.text:0000000180005F9F mov eax, r14d
.text:0000000180005FA2 lock xadd [rdi+8], eax
.text:0000000180005FA7 cmp eax, 1
.text:0000000180005FAA jnz short loc_180005FEA
.text:0000000180005FAC mov rax, [rdi]
.text:0000000180005FAF mov rcx, rdi
.text:0000000180005FB2 call qword ptr [rax]
.text:0000000180005FB4 lock xadd [rdi+0Ch], r14d
.text:0000000180005FBA cmp r14d, 1
.text:0000000180005FBE jnz short loc_180005FC9
.text:0000000180005FC0 mov rax, [rdi]
.text:0000000180005FC3 mov rcx, rdi
.text:0000000180005FC6 call qword ptr [rax+8]
.text:0000000180005FC9
.text:0000000180005FC9 loc_180005FC9: ; CODE XREF: CR_maybeParseWithLambda+4E↑j
.text:0000000180005FC9 mov [rbx+8], rsi
.text:0000000180005FCD mov [rbx], rbp
.text:0000000180005FD0
.text:0000000180005FD0 loc_180005FD0: ; CODE XREF: CR_maybeParseWithLambda+81↓j
.text:0000000180005FD0 mov r14, [rsp+28h+arg_0]
.text:0000000180005FD5
.text:0000000180005FD5 loc_180005FD5: ; CODE XREF: CR_maybeParseWithLambda+8A↓j
.text:0000000180005FD5 ; DATA XREF: .pdata:0000000180483888↓o ...
.text:0000000180005FD5 mov rbx, [rsp+28h+arg_8]
.text:0000000180005FDA mov rbp, [rsp+28h+arg_10]
.text:0000000180005FDF mov rsi, [rsp+28h+arg_18]
.text:0000000180005FE4 add rsp, 20h
.text:0000000180005FE8 pop rdi
.text:0000000180005FE9 retn