白加黑

白

白指的是带有有效数字签名的可执行文件,通常指exe文件

黑

指的是我们恶意代码所在文件,通常是dll文件

针对白加黑的制作上,白程序我们一般只需要寻找,不需要手动编写,黑程序才是我们实际编写的

针对白加黑,我们重点就两件事,寻找白文件和写黑dll文件

上线原理

白程序(exe)→dll→dllmain/导出函数中的代码,其中dll是我们自己编写的,里面的代码我们可以自定义

dll文件结构

使用dll的好处是程序不需要运行之初加载所有代码,只有在程序需要函数的时候才从DLL中取出

framework.h

用于包含项目中需要使用的头文件,可以看到默认包含了windows头文件 image.png

pch.h

是预编译标头文件,dll的导出函数在这里被定义 image.png

dllmain.cpp

文件程序的入口点,在dllmain.cpp实现的在pch.h中定义函数,当然也可以在其他cpp文件中实现,如pch.cpp等 image.png

pch.cpp

一般用于存放我们的导出函数 image.png

DllMain

DllMain是系统动态链接库的可选入口点,也就是常说的入口函数

当系统启动或者中止的进程或者线程的时候,它会使用进程的第一个线程为每个加载的dll调用函数

当dll使用LoadLibrry加载和使用FreeLibrary函数卸载dll时,系统还会调用该函数的入口点函数

// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "pch.h"

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH://当DLL被进程加载时执行,每个进程只初始化一次
    case DLL_THREAD_ATTACH://当线程被创建时调用
    case DLL_THREAD_DETACH://当线程结束时调用
    case DLL_PROCESS_DETACH://当DLL被进程卸载时执行
        break;
    }
    return TRUE;
}

编译

导出函数

在pch.cpp中编写一个导出函数

// pch.cpp: 与预编译标头对应的源文件

#include "pch.h"

// 当使用预编译的头时,需要使用此源文件,编译才能成功。
int sum(int a, int b) {
    return a + b;
}

然后在pc.h中定义该函数

#ifdef Dll1_EXPORTS
#define API_DECLSPECKM _declspec(dllexport)
#else
#define API_DECLSPECKM _declspec(dllimport)

#endif // 
extern "C" API_DECLSPECKM int main(int a, int b);

查看导出函数

打开Developer Command Promopt for VS

# 查看dll库中包含哪些函数
dumpbin /exports a.dll
 
# 查看exe中加载了哪些动态库
dumpbin /imports a.exe
 
# 查看lib库中包含了那些函数
dumpbin /all /rawdata:none a.lib
 
# 查看obj中包含了哪些函数
dumpbin /all /rawdata:none d.obj
 
# 查看dll信息
dumpbin /headers a.dll

dll调试

由于dll不能直接运行,因此在vs中不能直接运行dll文件,需要我们自添加exe来调试dll,比如说

int main(){
    HMODULE hDll1=LoadLibrary(L"Dll1.dll");
    typedef int(*pSum)(inta ,int b);
    pSum sum=(pSum)GetProcAddress(hDll1,"sum")
    cout<<sum(1,2)<<endl;
}

寻找白程序

知道了dll是怎么回事,接下来就可以使用白加黑挖掘了,这里推荐工具批量挖掘 使用SkyShadow,查看白文件

然后正常将shellcode进行注入就行

但同时360对于黑dll文件查杀严格,会对dll拉黑的文件名查杀