Assembly 如何简化将自身引用为参数的函数?(这意味着什么)

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

我经常遇到调用自身的函数(在IDA生成的伪代码中),例如:

  • 由于反汇编是
    调用qword ptr[rax]
    ,这不能简化为
    result=lambda()
    
  • 为什么在伪代码中函数将自身作为参数
  • 当出现诸如
    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()
    否。反编译器检测到传入的变量可能是被调用函数的参数

    例如,
    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