从外部进程调用函数而无需导出函数(C语言相关)

3
我正在尝试找出如何在不导出函数的情况下调用函数。
好的,我有一个包含“add”定义的exe文件。这个exe是一个win32控制台应用程序,并加载了一个DLL。该DLL也旨在使用来自exe文件的add函数(无需导出)。
以下是我的主win32控制台应用程序文件:
#include <windows.h>
#include <stdio.h>

#pragma auto_inline ( off )

int add ( int a, int b )
{
    printf( "Adding some ints\n" );
    return a + b;
}

int main ( )
{
    HMODULE module = NULL;

    if ( (module = LoadLibrary( L"hook.dll" )) == NULL )
    {
        printf( "Could not load library: %ld\n", GetLastError() );
        return 0;
    }

    add( 3, 5 );

    FreeLibrary( module );

    return 0;
}

这里是hook.dll的代码:

#include <windows.h>
#include <stdio.h>
#include <detours.h>

static int (*add) ( int a, int b ) = ( int (*)( int a, int b ) ) 0x401000;

int Detoured_add ( int a, int b )
{
    return add( a, b );
}

BOOL WINAPI DllMain ( HINSTANCE hDll, DWORD reason, LPVOID reserved )
{
    if ( reason == DLL_PROCESS_ATTACH )
    {
        DetourTransactionBegin();
        DetourAttach( (PVOID*) &add, Detoured_add );
        DetourTransactionCommit();

    }
    else if ( reason == DLL_PROCESS_DETACH )
    {
        DetourTransactionBegin();
        DetourDetach( (PVOID*) &add, Detoured_add );
        DetourTransactionCommit();
    }

    return TRUE;
}

我反汇编了我的Win32控制台应用程序,以查找add函数的地址。

.text:00401000 ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
.text:00401000
.text:00401000
.text:00401000 sub_401000      proc near               ; CODE XREF: sub_401020:loc_40104Bp
.text:00401000                 push    offset aAddingSomeInts ; "Adding some ints\n"
.text:00401005                 call    ds:printf
.text:0040100B                 add     esp, 4
.text:0040100E                 mov     eax, 8
.text:00401013                 retn
.text:00401013 sub_401000      endp

当我调用LoadLibrary时,它返回998,我认为这是访问冲突的错误代码。我猜这很有道理,因为该内存区域可能受到保护。

有什么提示吗?

(另外,我使用的反汇编工具是免费版的Ida Pro,而Detours库是由Microsoft提供的。)


我对Detours不是很了解,也不确定它能否以这种方式使用。但你确定add()的地址在运行时实际上会是0x401000吗?模块不能被重新定位或其他什么吗? - Alex Jasmin
没错,我也不太确定地址,因为我对这种东西还很陌生。 - Tr41n
我会继续努力工作并向您汇报我的发现。 - Tr41n
1
你正在给自己带来很多麻烦和痛苦。从实际的角度来看,你有两个选择:要么导出函数,要么让你的可执行文件传递一个指向需要调用的函数的指针。 - Jerry Coffin
1个回答

1

模块在加载时会被重新定位。您应该找到已加载模块的基地址并自行重新定位地址。此外,您可以使用[DebugHelp][1]库通过符号名称检索函数地址,而不是硬编码它。


+1 我想可以使用 DebugHelp。不过你需要编译带有调试信息的模块。 - Alex Jasmin
我发现将反汇编的原始十六进制代码值作为函数指针输入是可行的,但在Win32控制台应用程序中不行。Windows DEP会阻止它。所以,如果只是从主可执行文件中获取该值,则似乎可以正常工作,但如果是从主可执行文件使用的外部模块中获取该值,则可以尝试以下方法:HMODULE handle = GetModuleHandleA("another.dll"); int (add)( int a, int b ) = ( int ()(int,int) )( (DWORD)handle + (DWORD)0x2329381 ); - Tr41n

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接