ShellCode注入程序

发布时间:2023年12月18日

程序功能是利用NtQueueApcThreadEx注入ShellCode到一个进程中,程序运行后会让你选择模式,按1为普通模式,所需的常规API接口都是使用Windows原本正常的API;在有游戏保护的进程中Windows原本正常的API无法使用,这时候需要选择内核模式,按2选择内核模式。

内核模式下使用的一些关键API都是我自己在ring0从0实现的,本帖仅开源普通模式下的代码。内核模式下使用的关键API以及调用框架不开源。

选择模式之后需要输入被注入进程的PID

项目包含三个源代码文件:1.源.cpp
2.fun.asm
3.fun.h

首先是源.cpp文件代码:

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

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

插入代码

```/*

*?函数原型:

NTSTATUS NtQueueTHreadApcEx(

_in HANDLE thread,

_in UCHAR flags,0:常规用户APC,1:特殊用户APC

_in PAPCFUNC apcRoutine,

_in PVOID context1,

_in PVOID arg1,

_in PVOID arg2

);

需要从Ntdll.dll模块显式导出(GetProcAddress)

*/

#define _CRT_SECURE_NO_WARNINGS

#include<stdio.h>

#include<Windows.h>

#include<Tlhelp32.h>

#include"fun.h"

HWND hwndG?=?0;

BOOL?CALLBACK EnumWindowsProc(

????HWND hwnd,

????LPARAM lParam)

{

????WCHAR path[MAX_PATH]?=?{?0?};

????WCHAR*?text?=?(WCHAR*)lParam;

????GetWindowText(hwnd, path, MAX_PATH);

????if?(lstrcmpW(text, path)?==?0)

????{

????????hwndG?=?hwnd;

????????return?FALSE;

????}

????else

????{

????????hwndG?=?0;

????????return?TRUE;

????}

}

DWORD WINAPI GetThreadIdByProcessId(DWORD dwProcessId)

{

????THREADENTRY32 th32;

????th32.dwSize?=?sizeof(THREADENTRY32);

????DWORD dwThreadId?=?0;

????HANDLE hdTool?=?CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, dwProcessId);

????if?(Thread32First(hdTool, &th32))

????{

????????do

????????{

????????????if?(th32.th32OwnerProcessID?==?dwProcessId)

????????????{

????????????????dwThreadId?=?th32.th32ThreadID;

????????????????//printf("%d\n", dwThreadId);

????????????????break;

????????????}

????????}?while?(Thread32Next(hdTool, &th32));

????}

????else

????{

????????DWORD dwErro?=?GetLastError();

????????//printf("遍历进程失败!——%d", dwErro);

????????return?dwErro;

????}

?????

????return?dwThreadId;

}

BOOL?WINAPI PrivilegeAdjust()

{

????BOOL?flag;

????HANDLE token;

????if?(!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token))

????{

????????//printf("打开令牌失败!\n");

????????flag?=?FALSE;

????}

????LUID pid;

????if?(!LookupPrivilegeValueA(NULL,?"SeDebugPrivilege", &pid))

????{

????????//printf("查看特权ID失败\n");

????????flag?=?FALSE;

????}

????TOKEN_PRIVILEGES tp;

????tp.PrivilegeCount?=?1;

????tp.Privileges[0].Luid?=?pid;

????tp.Privileges[0].Attributes?=?SE_PRIVILEGE_ENABLED;

????if?(!AdjustTokenPrivileges(token, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL))

????{

????????//printf("提升特权失败!\n");

????????flag?=?FALSE;

????}

????return?TRUE;

}

typedef?BOOL(*MYTYPE)(HANDLE, LPVOID, LPVOID, SIZE_T, SIZE_T*);

typedef HANDLE(*OPPS)(DWORD,?BOOL, DWORD);

typedef?BOOL(*WRMEMEX)(HANDLE, LPVOID, LPVOID, SIZE_T, SIZE_T*);

typedef HANDLE(*OPTS)();

typedef ULONG64(*GETPEB)(DWORD);

typedef NTSTATUS(*NTQUEAPC)(HANDLE, UCHAR, PVOID, PVOID, PVOID, PVOID);

WRMEMEX Read;

WRMEMEX Write;

OPPS OpenPro;

OPTS OpenThr;

NTQUEAPC NtQueueUserApcEx;

VOID InitFrmak()

{

????printf("内核\n");

????NtQueueUserApcEx?=?NULL;

????HMODULE mod?=?LoadLibraryA("ApiSystemCall.dll");

????Read?=?(WRMEMEX)GetProcAddress(mod,?"YhReadProcessMemory");

????Write?=?(WRMEMEX)GetProcAddress(mod,?"YhWriteProcessMemory");

????OpenPro?=?(OPPS)GetProcAddress(mod,?"YhOpenProcess");

????OpenThr?=?(OPTS)GetProcAddress(mod,?"YhOpenThread");

????NtQueueUserApcEx?=?(NTQUEAPC)GetProcAddress(GetModuleHandleA("ntdll.dll"),?"NtQueueApcThreadEx");

????if?(NtQueueUserApcEx?==?NULL)

????{

????????MessageBoxA(NULL,?"获取函数失败",?0,?0);

????}

}

VOID InitFrmakEx()

{

????NtQueueUserApcEx?=?NULL;

?????

????printf("普通\n");

????Read?=?ReadProcessMemory;

????Write?=?WriteProcessMemory;

????OpenPro?=?OpenProcess;

????OpenThr?=?OpenThread;

????NtQueueUserApcEx?=?(NTQUEAPC)GetProcAddress(GetModuleHandleA("ntdll.dll"),?"NtQueueApcThreadEx");

????if?(NtQueueUserApcEx?==?NULL)

????{

????????MessageBoxA(NULL,?"获取函数失败",?0,?0);

????}

}

typedef VOID(*FUN)();

int?main()

{

????DWORD pid;

????SIZE_T size=0;

????CONTEXT text;

????VirtualProtect(fun,?0x60, PAGE_EXECUTE_READWRITE, &pid);

????*(ULONG64*)(&(((UCHAR*)fun2)[0x34]))?=?MessageBoxA;

????*(ULONG64*)(&(((UCHAR*)fun2)[0x9f]))?=?SetWindowsHookExA;

????//fun(NULL,NULL,NULL);

????printf("请输入模式:\n1.普通模式\n2.内核模式\n");

????scanf("%d", &size);

????(size==1)? InitFrmakEx(): InitFrmak();

????printf("请输入进程PID:\n");

????scanf("%d", &pid);

????PrivilegeAdjust();

?????

????HANDLE hd?=?OpenPro(PROCESS_ALL_ACCESS, FALSE, pid);

????PVOID mem?=?VirtualAllocEx(hd, NULL,?0X1000, MEM_COMMIT, PAGE_EXECUTE_READWRITE);

????DWORD tid?=?GetThreadIdByProcessId(pid);

????HANDLE td;

????if?(size?==?1)

????{

????????td?=?OpenThr(THREAD_ALL_ACCESS,FALSE,tid);

????}

????else

????{

????????td?=?OpenThr(tid, hd, THREAD_ALL_ACCESS, FALSE);

????}

????if?(!Write(hd, mem, fun2,?0x100, &size))

????{

????????MessageBoxA(0,?"写入失败",?0,?0);

????}

????SuspendThread(td);

????NTSTATUS code?=?NtQueueUserApcEx(td,?1, (PVOID)(((ULONG64)mem)+0x53), tid,?0,?0);

????if(code!=0)

????{

?????????

????????printf("%x\n", code);

????????MessageBox(0,?0,?0,?0);

????}

????ResumeThread(td);

????system("pause");

????return?0;

}

fun.asm文件

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

.code

MessageBoxA proto

fun2 proc

????push rbp;

????mov rbp,rsp;

????sub rsp,060h;

????xor rax,rax;

????cmp?rcx,rax;

????jnz sub_1;

????cmp?rdx,09h;;虚拟键代码0x9为键盘的TAB键

????jnz sub_1;

????xor rcx,rcx;

????lea rdx,qword ptr[lab_2];

????xor r8,r8;

????xor r9,r9;

????mov rax,qword ptr[lab_1];

????call rax;

sub_1:

????mov rsp,rbp;

????pop rbp;

????ret;

fun2 endp

lab_1:

????db?00h;

????db?00h;

????db?00h;

????db?00h;

????db?00h;

????db?00h;

????db?00h;

????db?00h;

lab_2:

????db?0c2h;

????db?0edh;

????db?0bbh;

????db?0afh;

????db?0cch;

????db?0dah;

????db?0cah;

????db?0c7h;

????db?0c9h;

????db?0b5h;

????db?0b1h;

????db?0c6h;

????db?0a3h;

????db?0a1h;

????db?00ah;

????db?00h;

????db?00h;

????db?00h;

????db?00h;

????db?00h;

????db?00h;

????db?00h;

????db?00h;

fun proc

?????

????push rbp;

????mov rbp,rsp;

????sub rsp,080h;

????mov r9,rcx;

????mov rcx,02h;

????lea rdx,qword ptr [fun2];

????xor r8,r8;

????mov rax,qword ptr [sub_2];

????call rax;

????cmp?rax,0;

????jnz lab_3;

????xor rcx,rcx;

????xor rdx,rdx;

????xor r8,r8;

????mov r9,02h;

????mov rax,qword ptr [lab_1];

????call rax;

lab_3:

????mov rsp,rbp;

????pop rbp;

????ret;

sub_2:

????db?00h;

????db?00h;

????db?00h;

????db?00h;

????db?00h;

????db?00h;

????db?00h;

????db?00h;

fun endp

end

fun.h文件

1

2

3

#pragma once

#include<Windows.h>

void fun(PVOID a, PVOID b, PVOID c);

shellCode的功能是给被注入进程设置一个键盘钩子,TAB键。

?

?

文章来源:https://blog.csdn.net/jmm18363027827/article/details/135024427
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。