返回
顶部

(所有压缩包的密码均为1)

references:

一直没有找到比较好的shellcode混淆方法,尝试过直接使用OLLVM来编译出asm文件,之后再进行链接,但是总是会报一堆错误,后来尝试了使用PE2SHC来将混淆后的PE直接转换为shellcode进行注入,但是被注入的程序总是会莫名其妙的崩溃,而且使用PE2SHC很容易被杀软识别出来,因为他在最后面添加的那一段PE Loader的代码特征太明显了

为了解决以上的问题,我仔细看了一下ReflectiveDLLInjection项目的源代码,最终形成了下面的解决方案:

  • 在编写shellcode代码的时候除了调用GetModuleHandleAGetProcAddress这两个kernel32.dll中的API用于加载kernel32.dll并从中获取LoadLibraryAGetProcAddress这两个函数外,不再直接调用win32 API
  • 不使用除了win32 API之外的函数,如printf
  • 在链接的时候,指定程序入口为main函数

其中第一点和第二点都是为了在注入shellcode的时候,不在目标进程中额外加载其他dll,因为在我的认知范围内,还没有哪个程序运行的时候不需要加载kernel32.dll,因此我们可以直接使用目标进程现成的kernel32.dll模块

对于第三点,大家可以参考这篇文章,默认情况下VS生成的PE文件的EntryPoint并不是main函数,而是__security_init_cookie,之后它会调用__scrt_common_main_seh,该函数最终会调用main函数,但是我们并不需要前面这些进行初始化和setup的函数,而且他们正是导致目标程序在注入之后崩溃的原因,在shellcode项目中进行如下设置即可

image-20231029234142684

image-20231029231930369

在这种设置下生成的PE文件的导入表只有两个导入函数

image-20231029234614699

在PE Loader中,只有两个地方需要对代码中的内存地址进行修正,一个是导入表,另一个就是base relocation

我们只需要在进行这两步操作的时候,使用目标进程中kernel32.dll模块的地址和PE文件将要加载到目标进程中的内存地址(基地址)即可

思路就是先在注入程序中把PE文件加载好,然后整个拷贝到目标进程中就行了

下面是一个例子,我们的shellcode只干了一件事,就是加载lsasrv.dll,shellcode运行完成后,injector会释放在目标进程中开辟的内存空间,injector接收两个参数,第一个是目标进程的PID,第二个是shellcode的PE文件

动画asdasdasd

injector.exe+PE.exe

这两个文件都已经经过了混淆处理

injector.exe源代码

PE.exe的源码:

#include<Windows.h>

typedef
FARPROC
(NTAPI* PNT_GetProcAddress)(
    HMODULE hModule,
    LPCSTR  lpProcName
    );

typedef
HMODULE
(NTAPI* PNT_LoadLibraryA)(
    LPCSTR lpLibFileName
    );

int main() {
    HMODULE ahndleeeeer = GetModuleHandleA("kernel32.dll");
    DWORD64   _kernel32_base_addr = reinterpret_cast<DWORD64>(ahndleeeeer);
    PNT_LoadLibraryA NT_LoadLibraryA = (PNT_LoadLibraryA)GetProcAddress(ahndleeeeer, "LoadLibraryA");
    PNT_GetProcAddress NT_GetProcAddress = (PNT_GetProcAddress)GetProcAddress(ahndleeeeer, "GetProcAddress");
    NT_LoadLibraryA("C:\\windows\\system32\\lsasrv.dll");
}