如何在C+;中调用此x86 ASM调用+;使用typedef或inline 我在5个不同的地方发现这个调用子10636f0 >试图找出如何从被注入目标应用程序的C++ DLL调用它,以便它完全访问该应用程序中的所有调用。

如何在C+;中调用此x86 ASM调用+;使用typedef或inline 我在5个不同的地方发现这个调用子10636f0 >试图找出如何从被注入目标应用程序的C++ DLL调用它,以便它完全访问该应用程序中的所有调用。,c++,assembly,x86,inline,typedef,C++,Assembly,X86,Inline,Typedef,我有一张图表,上面列出了所有被调用的地方,这些调用的大部分都是在它上面的另一个调用之后被剪切的,以确保它的完整性 我读了很多关于stackoverflow的问题,从Necrolis那里找到了一些很好的答案,说如果是EDX,那么你可以使用u fastcall。 我用谷歌搜索了一下ECX,它似乎也被用来快速呼叫,所以ECX或EDX都是指快速呼叫 但是它调用的函数使用包装器 sub esp, 5F4h add esp, 5F4h retn 8 我不知道这是关于再次做大量研究的事

我有一张图表,上面列出了所有被调用的地方,这些调用的大部分都是在它上面的另一个调用之后被剪切的,以确保它的完整性

我读了很多关于stackoverflow的问题,从Necrolis那里找到了一些很好的答案,说如果是EDX,那么你可以使用u fastcall。 我用谷歌搜索了一下ECX,它似乎也被用来快速呼叫,所以ECX或EDX都是指快速呼叫

但是它调用的函数使用包装器

sub     esp, 5F4h
add     esp, 5F4h
retn    8
我不知道这是关于再次做大量研究的事情,我认为开头的
子ESP,XXX
和结尾的
添加ESP,XXX
仅用于cdecl转换

我当前的代码如下所示

typedef void(__fastcall *TThreeParamter)(int, int, int);
typedef void(__fastcall *TTwoParamter)(int, int);
typedef void(__fastcall *TOneParamter)(int);
typedef void(__fastcall *TZeroParamter)();

TTwoParamter sub_10636F0 = (TTwoParamter)(DWORD)GetModuleHandle(NULL) + 0xC636EF;

//the call
sub_10636F0(0x11223344, 0x55667788);

不要问我为什么0xC636EF与sub中的
10636F0
不同,我可以告诉你,在调试器中检查后,它会进入正确的sub,sub会在每次重新启动程序时不断移动,这似乎是一种保护方法,或者可能是因为这个程序加载了超过50个dll,地址需要移动

我尝试了所有不同的配置,2个int,3个int都没用


IDA将此方法检测为3个参数,但最后一个参数在反编译的pesudo代码中没有使用,我无法理解

伪代码看起来像这样(我对它做了大量修改,比如将它从uuuThisCall更改为fastcall)

来自IDA的伪代码

这是默认情况下IDA推荐的代码

char __userpurge sub_10636F0@<al>(int a1@<ecx>, __int128 a2@<xmm0>, int a3, int a4)
{
  int v4; // esi@1
  int v5; // ebx@1
  SOCKET v6; // ebp@1
  int v7; // eax@2
  int v8; // ecx@3
  int v9; // eax@8
  char v11; // [sp+8h] [bp-5FCh]@7
  int v12; // [sp+10h] [bp-5F4h]@4
  int v13; // [sp+24h] [bp-5E0h]@2
  int v14; // [sp+28h] [bp-5DCh]@2
  int v15; // [sp+2Ch] [bp-5D8h]@2
  int v16; // [sp+30h] [bp-5D4h]@2
  char v17; // [sp+34h] [bp-5D0h]@2
  signed int v18; // [sp+5E4h] [bp-20h]@2
  int v19; // [sp+5E8h] [bp-1Ch]@2
  int v20; // [sp+5F0h] [bp-14h]@2
  __int16 v21; // [sp+5F8h] [bp-Ch]@2

  v4 = a4;
  v5 = a1;
  v6 = *(_DWORD *)(a3 + 220);
  if ( v6 == -1 )
    return 0;

   //Snipped code

  if ( v9 >= 0 && v9 == *(_DWORD *)(v4 + 1492) )
    return 1;
  return 0;
}


在ASM中调用此函数

我不知道这是怎么回事,我想我又做了大量的研究 开头的
子ESP,XXX
和结尾的
添加ESP,XXX
仅用于
\u cdecl
转换

不,它用于所有使用局部变量的函数(具体操作方式略有不同,但堆栈空间需要通过从ESP中减去来分配,通过向堆栈指针添加相同的量来“释放”)

<>但是, Ret 8 确实表明调用约定不是“代码> > CCDCL</代码>,而是被调用方清理栈的一个。有一些不同的匹配,但是我感觉它是C++代码和成员函数,它会使它成为代码>这个调用< /C> >这确实使它有点难以实现。是的,因为您想在
ECX
中使用
这个

ret8
表示函数有8个字节的参数,因此有两个
int
void*
变量

我还不相信有一种简单的方法可以做到这一点。你可以这样做。创建一个带有两个参数的虚拟函数的
class X

class X
{
   virtual void Func(int x, int y) { }
};
然后找出编译器将vtable放在哪里,并修改
func
的vtable以指向目标函数,而不是类的空实现

现在,您可以使用
X
创建实例:

 X* p = new X;
然后调用
func

 p->func(1, 2);
但是,如果您运气不好,编译器不会意识到您弄乱了vtable,最终直接调用了函数。因此,您可能需要对单独的编译和其他内容进行一些技巧

换句话说,你的工作被削减了。但是如果你不需要耍一点花招的话,逆向工程就不会有任何乐趣

当然,作弊者的方法是只编写几行内联汇编程序,如下所示:

void CallMyFunc(void *func, int a, int b, int c)
{
    __asm(mov ecx, a
          push b
          push c
          call *func);
}

[P>]自从我上次写Windows内联汇编代码以来,大约有10年了,所以如果语法不太正确,就要道歉——把它看作是一个“草图”,然后修改它,直到它实际编译……

该函数使用uu thiscall调用约定并接受三个参数。第一个参数是
this
指针,在ECX中传递。最后两个参数在堆栈中传递。该函数从堆栈中弹出其参数。第一个参数和第二个参数都不是
int
类型。它们都是指针。第一个参数指向类类型,函数是其中的一个成员,而第二个指向某种聚合类型,可能也是一个类。另外,您提到的
add
/
sub
with
esp
只是用于分配和释放局部变量,并应用于各种约定。我不介意在内联汇编中执行此操作,感谢您对此进行了澄清它是8个字节(2个DWORD参数),现在至少对我来说有点意义了。我只有2个参数来处理int这个和int数据包,无法找出第3个。你的粗略草图参数正确吗?看起来是3而不是2?找到了这个
 X* p = new X;
 p->func(1, 2);
void CallMyFunc(void *func, int a, int b, int c)
{
    __asm(mov ecx, a
          push b
          push c
          call *func);
}