ShellCode注入程序

文章介绍了如何使用NtQueueApcThreadEx在Windows中注入ShellCode,支持两种模式:普通模式通过常规API,适用于无游戏保护进程;内核模式下使用自定义内核级API,针对受保护进程。作者提供了源代码片段和必要的函数导出。
摘要由CSDN通过智能技术生成

程序功能是利用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, "获取函数失败"00);

    }

}

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, "获取函数失败"00);

    }

}

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"写入失败"00);

    }

    SuspendThread(td);

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

    if(code!=0)

    {

         

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

        MessageBox(0000);

    }

    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键。

 

 

Shellcode Helper v1.62 Coded by TeLeMan (c) 2008-2013 Usage: schelper.exe [options] Options: -i [input file] input file (Default: stdin) -o [output file] output file (Default: stdout) -s input file format (Default: Auto-Detection) -sb input file format is Binary -sp the input file format's parameters -d output file format (Default: C format) -db output file format is Binary -dp the output file format's parameters -search get the start offset by the pattern: e.g. PK\x03\x04 -soff fix the match offset after searching (Default: 0) -off convert the input file from the offset (Default: 0) -len convert the input file with the length (Default: 0 - MAX) -en [encoder] encode shellcode (Default: XorDword) -de [encoder] decode shellcode (Default: Auto-Detection) -ex exclude characters: e.g. 0x00,0x01-0x1F,0xFF (Default: 0x00) -in incude characters only -ep the encoder's parameters -t [pid] execute or inject shellcode into process for testing -td [pid] execute or inject shellcode into process for debugging -stack put shellcode into stack and execute it (ESP is the shellcode start) -noinfo display no normal messages except error messages Available formats: 0 - C 1 - C(HexArray) 2 - Perl 3 - Python 4 - Ruby 5 - JavaScript(Escape) 6 - VBScript(Escape) 7 - Pascal 8 - MASM(Data) 9 - HexDump 10 - BitString 11 - HexString 12 - HexArray(C like) 13 - Base64 14 - Binary 15 - HexString(C like) 16 - HexString(Escape) 17 - HexString(JavaScript,UNICODE) 18 - URI(ISO-8859-1) 19 - XML(PCDATA) 20 - BigNumber 21 - BigNumber(Hex) 22 - BigNumber(BaseX) 23 - FloatPoint 24 - UnixTimestamp 25 - GUID 26 - MASM(ASM) 27 - NASM 28 - YASM(ASM) 29 - FASM(ASM) 30 - JWASM(ASM) 31 - POASM(ASM) 32 - GOASM(ASM) 33 - GNU ASM Available encoders:
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值