Как написать инжектор для читов

EZcheats

Загрузка…

Simple C++/C DLL injector

Простенький инъектор .dll, созданный как альтернатива для GameOwner. Использует метод LoadLibrary.

Как использовать?

  1. Скачать injector.exe
  2. Распаковать в любую папку (желательно на флешку)
  3. Перенести вашу .dll в папку с инъектором
  4. Запустить инъектор и ввести название .dll
  5. Profit

Компиляция кода

Для компиляции кода нужен любой компилятор C++/C (например, GNU GCC Compiler).
Копируете injector.cpp и компилируете, полная копи-паста компатибилити чо.

В случае если Вы будете компилировать на чистом Си, нужно будет добавить в самое начало:

или же

typedef int bool;
#define true 1
#define false 0

Модификация кода

В сурс коде я прописал все как можно подробнее, все должно быть понятно.

Например, чтобы код инъекции работал не только в hl2.exe, а в любом, то можно написать следующий код:

char process_name[64];
scanf("%s",&process_name);
DWORD pID = GetTargetThreadIDFromProcName(process_name);

в данном случае пользователь должен будет вводить еще и имя процесса, чтобы код нормально работал.

Darwin


  • #1

Как написать Инжектор с нуля на C++​

В данной статье я вам расскажу и покажу как работает инжектор dll и как написать инжектор с нуля с методом LoadLibrary, я вам расскажу о каждом методе и последовательно как и что происходит, для новичков будет особенно полезная статья потому-что в интернете мало где можно найти написание инжектора с нуля на языке C++ давайте начнем

Что такое Инжектор? — это метод используемый для запуска кода в адресном пространстве другого процесса, заставляя его загружать библиотеку динамической компоновки
Соответственно для инжектора нам нужна динамическая библиотека которая будет выполнять код в адресном пространстве который мы освободим и создадим поток!

Давайте начнем писать сам инжектор, а с динамической библиотекой вы уже сами разберетесь или можете найти на форуме

Для начало нам нужно подключить несколько инклудов
#include <Windows.h>
#include <TlHelp32.h>

Нам нужна будет функция с помощью которой мы будем получать PID процесса, при открытий программ он генерируется всегда рандомно
Поэтому нам нужно получить его что бы на основе его открыть ручку процесса и предоставить нам полный доступ к процессу в User Mode

C++:

DWORD GetProcessID(const char* processName)
    {
        if (!processName)
            return 0;

        DWORD id = 0;
        HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);

        if (hSnap)
        {
            PROCESSENTRY32 pe32 = { sizeof(PROCESSENTRY32) };
            if (Process32First(hSnap, &pe32))
            {
                while (Process32Next(hSnap, &pe32))
                {
                    if (strcmp(processName, pe32.szExeFile) == 0)
                    {
                        id = pe32.th32ProcessID;
                        break;
                    }
                }
            }
        }CloseHandle(hSnap);
        return id;
    }

Теперь давайте в нашем main() найдем процесс нужной нам игры куда будем внедрять, откроем дескриптор процесса (получаем полный доступ) и освободим память и создадим наш поток адресного пространства

C++:

int main() {
   
    DWORD gameProcess = 0; // Создаем переменную под наш GetProcessID метод
    const char* DllPath = "anonymcheats.dll"; // Наша DLL которую инжектим, в данном случае он найдет рядом с инжектором (только)
   
    gameProcess = GetProcessID("csgo.exe");
    if (!gameProcess) { // Если наш процесс не был найден
        printf("Process csgo was not found");
    }
   
    // Если процесс найден открываем ручку
    HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, 0, gameProcess);
    if (hProcess == INVALID_HANDLE_VALUE) {
        // Если нашу ручку не удалось открыть
        printf("Handle Error");
    }
   
    void* allocated = VirtualAllocEx(hProcess, 0, MAX_PATH, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); // Освобождаем память под нашу DLL
            if (!WriteProcessMemory(hProcess, allocated, DllPath, strlen(DllPath) + '', 0)) // Записываем нашу DLL и проверяем что если неудалось записать
            {
                CloseHandle(hProcess);
                return false;
            }
            void* hThread = CreateRemoteThread(hProcess, 0, 0, (PTHREAD_START_ROUTINE)LoadLibraryA, allocated, 0, 0); // Создаем поток адресса которого мы освободили это наша DLL
            if (hThread != 0) // закрываем Handle
                CloseHandle(hThread);
   
            CloseHandle(hProcess); // Закрываем Handle Process
   
            printf("Inject Successfulled"); // Инжект произошел успешно
            return 0; // Возвращаем 0
}

  • #3

Как написать Инжектор с нуля на C++​

В данной статье я вам расскажу и покажу как работает инжектор dll и как написать инжектор с нуля с методом LoadLibrary, я вам расскажу о каждом методе и последовательно как и что происходит, для новичков будет особенно полезная статья потому-что в интернете мало где можно найти написание инжектора с нуля на языке C++ давайте начнем

Что такое Инжектор? — это метод используемый для запуска кода в адресном пространстве другого процесса, заставляя его загружать библиотеку динамической компоновки
Соответственно для инжектора нам нужна динамическая библиотека которая будет выполнять код в адресном пространстве который мы освободим и создадим поток!

Давайте начнем писать сам инжектор, а с динамической библиотекой вы уже сами разберетесь или можете найти на форуме

Для начало нам нужно подключить несколько инклудов
#include <Windows.h>
#include <TlHelp32.h>

Нам нужна будет функция с помощью которой мы будем получать PID процесса, при открытий программ он генерируется всегда рандомно
Поэтому нам нужно получить его что бы на основе его открыть ручку процесса и предоставить нам полный доступ к процессу в User Mode

C++:

DWORD GetProcessID(const char* processName)
    {
        if (!processName)
            return 0;

        DWORD id = 0;
        HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);

        if (hSnap)
        {
            PROCESSENTRY32 pe32 = { sizeof(PROCESSENTRY32) };
            if (Process32First(hSnap, &pe32))
            {
                while (Process32Next(hSnap, &pe32))
                {
                    if (strcmp(processName, pe32.szExeFile) == 0)
                    {
                        id = pe32.th32ProcessID;
                        break;
                    }
                }
            }
        }CloseHandle(hSnap);
        return id;
    }

Теперь давайте в нашем main() найдем процесс нужной нам игры куда будем внедрять, откроем дескриптор процесса (получаем полный доступ) и освободим память и создадим наш поток адресного пространства

C++:

int main() {
  
    DWORD gameProcess = 0; // Создаем переменную под наш GetProcessID метод
    const char* DllPath = "anonymcheats.dll"; // Наша DLL которую инжектим, в данном случае он найдет рядом с инжектором (только)
  
    gameProcess = GetProcessID("csgo.exe");
    if (!gameProcess) { // Если наш процесс не был найден
        printf("Process csgo was not found");
    }
  
    // Если процесс найден открываем ручку
    HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, 0, gameProcess);
    if (hProcess == INVALID_HANDLE_VALUE) {
        // Если нашу ручку не удалось открыть
        printf("Handle Error");
    }
  
    void* allocated = VirtualAllocEx(hProcess, 0, MAX_PATH, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); // Освобождаем память под нашу DLL
            if (!WriteProcessMemory(hProcess, allocated, DllPath, strlen(DllPath) + '', 0)) // Записываем нашу DLL и проверяем что если неудалось записать
            {
                CloseHandle(hProcess);
                return false;
            }
            void* hThread = CreateRemoteThread(hProcess, 0, 0, (PTHREAD_START_ROUTINE)LoadLibraryA, allocated, 0, 0); // Создаем поток адресса которого мы освободили это наша DLL
            if (hThread != 0) // закрываем Handle
                CloseHandle(hThread);
  
            CloseHandle(hProcess); // Закрываем Handle Process
  
            printf("Inject Successfulled"); // Инжект произошел успешно
            return 0; // Возвращаем 0
}

А теперь как обойти античит:)

  • #5

А как сделать что-бы с сайта дллка скачивалась

  • #6

А как сделать что-бы с сайта дллка скачивалась

C++:

URLDownloadToFile(0, L"ссылка на прямое скачивание", L"Путь, куда она скачается", 0, 0);

  • #7

Как написать Инжектор с нуля на C++​

В данной статье я вам расскажу и покажу как работает инжектор dll и как написать инжектор с нуля с методом LoadLibrary, я вам расскажу о каждом методе и последовательно как и что происходит, для новичков будет особенно полезная статья потому-что в интернете мало где можно найти написание инжектора с нуля на языке C++ давайте начнем

Что такое Инжектор? — это метод используемый для запуска кода в адресном пространстве другого процесса, заставляя его загружать библиотеку динамической компоновки
Соответственно для инжектора нам нужна динамическая библиотека которая будет выполнять код в адресном пространстве который мы освободим и создадим поток!

Давайте начнем писать сам инжектор, а с динамической библиотекой вы уже сами разберетесь или можете найти на форуме

Для начало нам нужно подключить несколько инклудов
#include <Windows.h>
#include <TlHelp32.h>

Нам нужна будет функция с помощью которой мы будем получать PID процесса, при открытий программ он генерируется всегда рандомно
Поэтому нам нужно получить его что бы на основе его открыть ручку процесса и предоставить нам полный доступ к процессу в User Mode

C++:

DWORD GetProcessID(const char* processName)
    {
        if (!processName)
            return 0;

        DWORD id = 0;
        HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);

        if (hSnap)
        {
            PROCESSENTRY32 pe32 = { sizeof(PROCESSENTRY32) };
            if (Process32First(hSnap, &pe32))
            {
                while (Process32Next(hSnap, &pe32))
                {
                    if (strcmp(processName, pe32.szExeFile) == 0)
                    {
                        id = pe32.th32ProcessID;
                        break;
                    }
                }
            }
        }CloseHandle(hSnap);
        return id;
    }

Теперь давайте в нашем main() найдем процесс нужной нам игры куда будем внедрять, откроем дескриптор процесса (получаем полный доступ) и освободим память и создадим наш поток адресного пространства

C++:

int main() {
 
    DWORD gameProcess = 0; // Создаем переменную под наш GetProcessID метод
    const char* DllPath = "anonymcheats.dll"; // Наша DLL которую инжектим, в данном случае он найдет рядом с инжектором (только)
 
    gameProcess = GetProcessID("csgo.exe");
    if (!gameProcess) { // Если наш процесс не был найден
        printf("Process csgo was not found");
    }
 
    // Если процесс найден открываем ручку
    HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, 0, gameProcess);
    if (hProcess == INVALID_HANDLE_VALUE) {
        // Если нашу ручку не удалось открыть
        printf("Handle Error");
    }
 
    void* allocated = VirtualAllocEx(hProcess, 0, MAX_PATH, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); // Освобождаем память под нашу DLL
            if (!WriteProcessMemory(hProcess, allocated, DllPath, strlen(DllPath) + '', 0)) // Записываем нашу DLL и проверяем что если неудалось записать
            {
                CloseHandle(hProcess);
                return false;
            }
            void* hThread = CreateRemoteThread(hProcess, 0, 0, (PTHREAD_START_ROUTINE)LoadLibraryA, allocated, 0, 0); // Создаем поток адресса которого мы освободили это наша DLL
            if (hThread != 0) // закрываем Handle
                CloseHandle(hThread);
 
            CloseHandle(hProcess); // Закрываем Handle Process
 
            printf("Inject Successfulled"); // Инжект произошел успешно
            return 0; // Возвращаем 0
}

ты забыл про
#include <stdio.h> ?)

  • #8

Как написать Инжектор с нуля на C++​

В данной статье я вам расскажу и покажу как работает инжектор dll и как написать инжектор с нуля с методом LoadLibrary, я вам расскажу о каждом методе и последовательно как и что происходит, для новичков будет особенно полезная статья потому-что в интернете мало где можно найти написание инжектора с нуля на языке C++ давайте начнем

Что такое Инжектор? — это метод используемый для запуска кода в адресном пространстве другого процесса, заставляя его загружать библиотеку динамической компоновки
Соответственно для инжектора нам нужна динамическая библиотека которая будет выполнять код в адресном пространстве который мы освободим и создадим поток!

Давайте начнем писать сам инжектор, а с динамической библиотекой вы уже сами разберетесь или можете найти на форуме

Для начало нам нужно подключить несколько инклудов
#include <Windows.h>
#include <TlHelp32.h>

Нам нужна будет функция с помощью которой мы будем получать PID процесса, при открытий программ он генерируется всегда рандомно
Поэтому нам нужно получить его что бы на основе его открыть ручку процесса и предоставить нам полный доступ к процессу в User Mode

C++:

DWORD GetProcessID(const char* processName)
    {
        if (!processName)
            return 0;

        DWORD id = 0;
        HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);

        if (hSnap)
        {
            PROCESSENTRY32 pe32 = { sizeof(PROCESSENTRY32) };
            if (Process32First(hSnap, &pe32))
            {
                while (Process32Next(hSnap, &pe32))
                {
                    if (strcmp(processName, pe32.szExeFile) == 0)
                    {
                        id = pe32.th32ProcessID;
                        break;
                    }
                }
            }
        }CloseHandle(hSnap);
        return id;
    }

Теперь давайте в нашем main() найдем процесс нужной нам игры куда будем внедрять, откроем дескриптор процесса (получаем полный доступ) и освободим память и создадим наш поток адресного пространства

C++:

int main() {
  
    DWORD gameProcess = 0; // Создаем переменную под наш GetProcessID метод
    const char* DllPath = "anonymcheats.dll"; // Наша DLL которую инжектим, в данном случае он найдет рядом с инжектором (только)
  
    gameProcess = GetProcessID("csgo.exe");
    if (!gameProcess) { // Если наш процесс не был найден
        printf("Process csgo was not found");
    }
  
    // Если процесс найден открываем ручку
    HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, 0, gameProcess);
    if (hProcess == INVALID_HANDLE_VALUE) {
        // Если нашу ручку не удалось открыть
        printf("Handle Error");
    }
  
    void* allocated = VirtualAllocEx(hProcess, 0, MAX_PATH, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); // Освобождаем память под нашу DLL
            if (!WriteProcessMemory(hProcess, allocated, DllPath, strlen(DllPath) + '', 0)) // Записываем нашу DLL и проверяем что если неудалось записать
            {
                CloseHandle(hProcess);
                return false;
            }
            void* hThread = CreateRemoteThread(hProcess, 0, 0, (PTHREAD_START_ROUTINE)LoadLibraryA, allocated, 0, 0); // Создаем поток адресса которого мы освободили это наша DLL
            if (hThread != 0) // закрываем Handle
                CloseHandle(hThread);
  
            CloseHandle(hProcess); // Закрываем Handle Process
  
            printf("Inject Successfulled"); // Инжект произошел успешно
            return 0; // Возвращаем 0
}

  • #9

C++:

URLDownloadToFile(0, L"ссылка на прямое скачивание", L"Путь, куда она скачается", 0, 0);

Спасибо

  • #12

Будет информация по поиску base для engine.dll и client.dll
И поиску паттернов, таких который hazedumper выкладывает?

  • #16

Когда нибудь может и пригодится, но я уверен, что очень годно)

// получаем хэндл процесса
    HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, GetProcId("gta_sa.exe"));
    // Указываем путь до нашей dll
    const char* DllPath = "C:\test.dll";
    // получаем размер строки нашего пути
    size_t SizePatch = strlen(DllPath) + 1;
    // выделяем память в gta_sa с размером нашей строки
    LPVOID pDllPath = VirtualAllocEx(hProcess, NULL, SizePatch, MEM_COMMIT, PAGE_READWRITE);
    // записываем наш путь в выделенную память
    WriteProcessMemory(hProcess, pDllPath, (LPVOID)DllPath, SizePatch, NULL);
    HMODULE kernel = GetModuleHandleA("Kernel32.dll"); // Получаем адрес kernel32
    DWORD Adr = (DWORD)GetProcAddress(kernel, "LoadLibraryA"); // получаем адрес функции LoadLibraryA
    // Вызываем LoadLibraryA в gta_sa.exe с аргументом "C:\test.dll" и возвращаем адрес нашего потока
    HANDLE hThread = CreateRemoteThread(hProcess, 0, 0,(LPTHREAD_START_ROUTINE)Adr, pDllPath, 0, 0);
    // Ожидаем завершение нашего потока(ждем завершения DllMain с аргументом DLL_PROCESS_ATTACH)
    WaitForSingleObject(hThread, INFINITE);
    // Закрываем дескриптор потока
    CloseHandle(hThread);
    // Освобождаем выделенную память
    VirtualFreeEx(hProcess, pDllPath, SizePatch, MEM_RELEASE);
    // Закрываем дескриптор процесса
    CloseHandle(hProcess);

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

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

231

232

233

234

235

236

237

238

239

240

241

242

243

244

245

246

247

248

249

250

251

252

253

254

255

256

257

258

259

260

261

262

263

264

265

266

267

268

269

270

271

272

273

274

275

276

277

278

279

280

281

282

283

284

285

286

287

288

289

290

291

292

293

294

295

296

297

298

299

300

301

302

.486                      ; create 32 bit code

.model flat, stdcall      ; 32 bit memory model

option casemap :none      ; case sensitive

;подключаем макросы и библиотеки

include masm32includewindows.inc

include masm32macrosmacros.asm

include masm32macroswindows.asm

uselib kernel32, user32, masm32

;структурка, в которую мы запишем свой jump

;на код нашего перехватчика функции

JUMPNEAR STRUCT

opcd BYTE ?

reladdr DWORD ?

JUMPNEAR ENDS

global_hook_cnt = 0

;Макрос для вызова оригинальной функции

;с оригинальными параметрами из тела перехватчика

;(пример — далее)

;func — имя перехваченной функции

;args — число аргументов

;have_prologue — имеет ли функция пролог

;(то есть, есть ли в ее начале команды mov edi,edi, push ebp; mov ebp, esp)

;(не задавайте для функций с числом аргументов больше 0, они всегда имеют пролог)

HOOK_ORIGINAL_CALL MACRO func:REQ, args:=< 0 >, have_prologue:=< 1 >

cnt = 0

REPEAT args

  push [ebp+(&args cnt + 1)*4]

  cnt = cnt + 1

ENDM

push offset @CatStr(next_inst_, %global_hook_cnt)

IF have_prologue EQ 1

  push ebp

  mov ebp,esp

ENDIF

mov eax,@CatStr(&func, _hook)

add eax,5

jmp eax

@CatStr(next_inst_, %global_hook_cnt):

global_hook_cnt = global_hook_cnt + 1

ENDM

;Макрос для вызова оригинальной функции

;с произвольными параметрами из любого места программы

;(если перехват установлен)

;(пример — далее)

;func — имя перехваченной функции

;have_prologue — имеет ли функция пролог

;(не задавайте для функций с числом аргументов больше 0, они всегда имеют пролог)

;params — список аргументов функции

HOOK_ORIGINAL_CALL_PARAM MACRO func:REQ, have_prologue:=< 1 >, params:VARARG

count = 0

FOR xparam, <params>

  count = count + 1

  @CatStr(var,%count) TEXTEQU @CatStr(&xparam)

ENDM

REPEAT count

  push @CatStr(var,%count)

  count = count 1

ENDM

push offset @CatStr(next_inst_, %global_hook_cnt)

IF have_prologue EQ 1

  push ebp

  mov ebp,esp

ENDIF

mov eax,@CatStr(&func, _hook)

add eax,5

jmp eax

@CatStr(next_inst_, %global_hook_cnt):

global_hook_cnt = global_hook_cnt + 1

ENDM

;Макрос для установки перехвата

;(пример — далее)

;lib — имя библиотеки, в которой содержится функция

;func — имя функции

;hook_label — название метки, по которой лежит наше тело перехватчика

;ifload — загрузить ли предварительно библиотеку (0 по умолчанию)

;have_prologue — имеет ли функция пролог

;(не задавайте для функций с числом аргументов больше 0, они всегда имеют пролог)

SET_HOOK MACRO lib:REQ, func:REQ, hook_label:REQ, ifload:=< 0 >, have_prologue:=< 1 >

%ECHO [The hook on &func is SET on @CatStr(%@Line) Line]

.data?

@CatStr(libn, %global_hook_cnt) dd ?

IFNDEF &func&_hook_

  @CatStr(&func, _hook) dd ?

  @CatStr(&func, _hook_) EQU <1>

ENDIF

IF have_prologue EQ 0

  IFNDEF &func&_prologue_

    @CatStr(&func, _prologue1) dw ?

    @CatStr(&func, _prologue2) db ?

    @CatStr(&func, _prologue3) dw ?

    @CatStr(&func, _prologue_) EQU <1>

  ENDIF

ENDIF

@CatStr(protect_, %global_hook_cnt) dd ?

.code

IF ifload EQ 1

  mov @CatStr(libn, %global_hook_cnt), FUNC(LoadLibrary,chr$(«&lib»))

ELSE

  mov @CatStr(libn, %global_hook_cnt), FUNC(GetModuleHandle,chr$(«&lib»))

ENDIF

mov @CatStr(&func, _hook), FUNC(GetProcAddress, @CatStr(libn, %global_hook_cnt), chr$(«&func»))

invoke VirtualProtect, @CatStr(&func, _hook), sizeof JUMPNEAR, PAGE_READWRITE,  offset @CatStr(protect_, %global_hook_cnt)

mov eax, @CatStr(&func, _hook)

IF have_prologue EQ 0

  mov cx, word ptr [eax]

  mov @CatStr(&func, _prologue1), cx

  mov cl, byte ptr [eax+2]

  mov @CatStr(&func, _prologue2), cl

  mov cx, word ptr [eax+3]

  mov @CatStr(&func, _prologue3), cx

ENDIF

assume eax: ptr JUMPNEAR

mov [eax].opcd, 0e9h

mov ecx, offset &hook_label

sub ecx,@CatStr(&func, _hook)

sub ecx,5

mov [eax].reladdr,ecx

assume eax:nothing

invoke VirtualProtect, @CatStr(&func, _hook), sizeof JUMPNEAR, @CatStr(protect_, %global_hook_cnt), offset @CatStr(protect_, %global_hook_cnt)

global_hook_cnt = global_hook_cnt + 1

ENDM

;Макрос для снятия перехвата

;(пример — далее)

;func — имя функции

;have_prologue — имеет ли функция пролог

;(не задавайте для функций с числом аргументов больше 0, они всегда имеют пролог)

REMOVE_HOOK MACRO func:REQ, have_prologue:=< 1 >

%ECHO [The hook on &func is REMOVED on @CatStr(%@Line) Line]

.data?

@CatStr(protect_, %global_hook_cnt) dd ?

.code

invoke VirtualProtect, @CatStr(&func, _hook), sizeof JUMPNEAR, PAGE_READWRITE,  offset @CatStr(protect_, %global_hook_cnt)

mov eax, @CatStr(&func, _hook)

IF have_prologue EQ 0

  mov cx, @CatStr(&func, _prologue1)

  mov word ptr [eax], cx

  mov cl, @CatStr(&func, _prologue2)

  mov byte ptr [eax+2], cl

  mov cx, @CatStr(&func, _prologue3)

  mov word ptr [eax+3], cx

ELSE

  mov word ptr [eax], 0ff8bh

  mov byte ptr [eax+2], 55h

  mov word ptr [eax+3], 0e589h

ENDIF

invoke VirtualProtect, @CatStr(&func, _hook), sizeof JUMPNEAR, @CatStr(protect_, %global_hook_cnt), offset @CatStr(protect_, %global_hook_cnt)

global_hook_cnt = global_hook_cnt + 1

ENDM

;начало примера

.code

;Тело нашего перехватчика для функции MessageBoxA

MyFunc:

push ebp

mov ebp,esp

;сюда можно поместить любой код

;[ebp+8] будет содержать первый аргумент функции

;[ebp+12] — второй аргумент и т.д.

;[ebp+4] будет содержать адрес возврата из функции

;вызываем оригинальную функцию с переданными параметрами

HOOK_ORIGINAL_CALL MessageBoxA, 4

;это эквивалентно записи

;HOOK_ORIGINAL_CALL_PARAM MessageBoxA,1,  [ebp+8], [ebp+12], [ebp+16], [ebp+20]

;а теперь подменим параметры (текст месадж бокса и иконку):

HOOK_ORIGINAL_CALL_PARAM MessageBoxA,1,  [ebp+8], chr$(«ахаха, перехват быдлозащиты!»), [ebp+16], MB_SYSTEMMODAL or MB_ICONERROR

;сюда тоже можно поместить любой код

;[ebp+8] будет содержать первый аргумент функции

;[ebp+12] — второй аргумент и т.д.

;[ebp+4] будет содержать адрес возврата из функции

;регистр eax будет содержать возвращенное функцией значение

;его можно заменить здесь

pop ebp

retn 4*4; (число аргументов функции MessageBoxA) * 4

;Тело перехватчика GetTickCount (помните, не факт, что это заработает на вашей системе, как я уже говорил!)

MyFunc2:

push ebp

mov ebp,esp

;сюда можно поместить любой код

;[ebp+4] будет содержать адрес возврата из функции

;вызываем оригинальную функцию

HOOK_ORIGINAL_CALL GetTickCount, 0, 0

;это эквивалентно записи

;HOOK_ORIGINAL_CALL_PARAM GetTickCount,0

;сюда тоже можно поместить любой код

;[ebp+4] будет содержать адрес возврата из функции

;регистр eax будет содержать возвращенное функцией значение, его можно заменить здесь

        mov eax,1337 ;вот мы и подменили ответ функции

pop ebp

ret ;(0 аргументов у GetTickCount, поэтому просто ret)

;Точка входа в DLL

LibMain proc instance:DWORD,reason:DWORD,reserved:DWORD

  LOCAL buf [20] :byte ;локальная переменная для хранения значения, возвращенного GetTickCount

  .if reason == DLL_PROCESS_ATTACH ;если наша DLL свежезагружена

    ;устанавливаем перехват MessageBoxA

    SET_HOOK user32.dll, MessageBoxA, MyFunc

    ;этот вызов будет перехвачен

    invoke MessageBox,0,chr$(«Hooked message box»),chr$(«Test»),MB_SYSTEMMODAL or MB_ICONINFORMATION

    ;этот вызов не будет перехвачен — он выполняется в обход тела перехватчика

    HOOK_ORIGINAL_CALL_PARAM MessageBoxA,1,  0,chr$(«Message box call without hook»),chr$(«Test»),MB_SYSTEMMODAL or MB_ICONINFORMATION

    ;снимаем перехват

    REMOVE_HOOK MessageBoxA

    ;этот вызов уже не перехватывается

    invoke MessageBox,0,chr$(«Original message box call»),chr$(«Test»),MB_SYSTEMMODAL or MB_ICONINFORMATION

    ;теперь установим перехват GetTickCount (эта функция не имеет пролога)

    SET_HOOK kernel32.dll, GetTickCount, MyFunc2, 0, 0

    ;этот вызов перехвачен, и значение тут подменено — 1337

    invoke GetTickCount

    ;преобразуем ответ функции в текстовый вид

    invoke wsprintf,addr buf,chr$(«%u»),eax

    ;выведем ответ, который вернула GetTickCount (он тут подменен)

    invoke MessageBox,0,addr buf,chr$(«Test»),MB_SYSTEMMODAL or MB_ICONINFORMATION

    ;убираем перехват

    REMOVE_HOOK GetTickCount, 0

    ;этот вызов уже не перехвачен

    invoke GetTickCount

    ;преобразуем ответ функции в текстовый вид

    invoke wsprintf,addr buf,chr$(«%u»),eax

    ;выведем ответ, который вернула GetTickCount

    invoke MessageBox,0,addr buf,chr$(«Test»),MB_SYSTEMMODAL or MB_ICONINFORMATION

    mov eax,1 ;сообщаем об успешной загрузке нашей DLL

  .endif

ret

LibMain ENDP

end LibMain

Привет господа форумчане. Давненько я не писал, но ничего страшного, скоро решатся пара бытовых проблем и выпуск статей нормализуется по 2 — 3 в неделю. А сегодня, мы поговорим немного не мало о технике DLL Инъекций и рассмотрим пару примеров.

Итак что такое DLL Инъекция?
Это тип атаки, который позволяет внедрять исполняемый код из DLL в процесс(исполняемую программу), что дает возможность выполнить код от имени пользователя под которым запущен процесс.

Рассмотрим 2 вида этой техники обычную DLL Injection и Dll Hijacking, а так же чем они отличаются.

DLL Injection
Как обычно в моем стиле, сразу к делу и на практике.
Задача: Заинжектить исполняемый код в программу Paint.
Для этого немного раскрою суть атаки.
Сначала мы ищем процесс, далее выделяем память для нашей DLL,
после чего загружаем её в новый поток внутри процесса, таким образом, инжектор выполнит код от имени пользователя программы.
Создаем DLL файл со следующим кодом.

C:

 #include <Windows.h>

extern "C" __declspec(dllexport) bool WINAPI DllMain(HINSTANCE hInstDll, DWORD fdwReason, LPVOID lpvReserved)
{
    switch (fdwReason)
    {
    case DLL_PROCESS_ATTACH:
    {
        MessageBox(NULL, "DLL INJECTION", "SPECIAL FOR CODEBY", MB_OK);
        break;
    }

    case DLL_PROCESS_DETACH:
        break;

    case DLL_THREAD_ATTACH:
        break;

    case DLL_THREAD_DETACH:
        break;
    }
    return true;
}

А далее напишем инжектор и разберем его по частям:

По сути основной смысл находится в этих двух методах

Код:

  public static int inject(string dllPath, Process tProcess)
        {
            Process targetProcess = tProcess; // Получаем процесс куда инжектим
            string dllName = dllPath; // Имя дллки что инжектим
            IntPtr procHandle = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ, false, targetProcess.Id); //открываем процесс для записи и чтения
            IntPtr loadLibraryAddr = GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA"); // Получаем адрес процесса
            IntPtr allocMemAddress = VirtualAllocEx(procHandle, IntPtr.Zero, (uint)((dllName.Length + 1) * Marshal.SizeOf(typeof(char))), MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); // Выделяем память под новый тред
            UIntPtr bytesWritten;
            WriteProcessMemory(procHandle, allocMemAddress, Encoding.Default.GetBytes(dllName), (uint)((dllName.Length + 1) * Marshal.SizeOf(typeof(char))), out bytesWritten); // Пишем в новую область памяти
            CreateRemoteThread(procHandle, IntPtr.Zero, 0, loadLibraryAddr, allocMemAddress, 0, IntPtr.Zero); // создаем поток в области памяти который запускает наш код
            return 0;
        }

// Здесь же просто вызов метода инжект
        public static void Execute()
        {
            string rawDLL = String.Empty;
            if (is64BitOperatingSystem)
            {
                rawDLL = Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), "DLL.dll");
            }
            else
            {
                rawDLL = Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), "DLL.dll");
            }
            // Execution of injection
            Process proc = Process.GetCurrentProcess(); //GetProcessesByName("mspaint")[0];
            Injection.inject(rawDLL, proc);
            isInjected = true;
        }

Полностью весь код, целиком:

Код:

using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.IO;
using System.Reflection;

namespace alphabotcsharp
{
    public class Injection
    {
        [DllImport("kernel32.dll")]
        public static extern IntPtr OpenProcess(int dwDesiredAccess, bool bInheritHandle, int dwProcessId);

        [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
        public static extern IntPtr GetModuleHandle(string lpModuleName);

        [DllImport("kernel32", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)]
        static extern IntPtr GetProcAddress(IntPtr hModule, string procName);

        [DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
        static extern IntPtr VirtualAllocEx(IntPtr hProcess,
            IntPtr lpAddress,
            uint dwSize,
            uint flAllocationType,
            uint flProtect);

        [DllImport("kernel32.dll", SetLastError = true)]
        static extern bool WriteProcessMemory(IntPtr hProcess,
            IntPtr lpBaseAddress,
            byte[] lpBuffer,
            uint nSize,
            out UIntPtr lpNumberOfBytesWritten);

        [DllImport("kernel32.dll")]
        static extern IntPtr CreateRemoteThread(IntPtr hProcess,
            IntPtr lpThreadAttributes,
            uint dwStackSize,
            IntPtr lpStartAddress,
            IntPtr lpParameter,
            uint dwCreationFlags,
            IntPtr lpThreadId);

        // privileges
        const int PROCESS_CREATE_THREAD = 0x0002;
        const int PROCESS_QUERY_INFORMATION = 0x0400;
        const int PROCESS_VM_OPERATION = 0x0008;
        const int PROCESS_VM_WRITE = 0x0020;
        const int PROCESS_VM_READ = 0x0010;

        // used for memory allocation
        const uint MEM_COMMIT = 0x00001000;
        const uint MEM_RESERVE = 0x00002000;
        const uint PAGE_READWRITE = 4;

        public static bool isInjected = false;
        [DllImport("kernel32.dll", SetLastError = true, CallingConvention = CallingConvention.Winapi)]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool IsWow64Process(
            [In] IntPtr hProcess,
            [Out] out bool wow64Process
        );

        static bool is64BitProcess = (IntPtr.Size == 8);
        static bool is64BitOperatingSystem = is64BitProcess || InternalCheckIsWow64();

        public static int inject(string dllPath, Process tProcess)
        {
            Process targetProcess = tProcess;
            string dllName = dllPath;
            IntPtr procHandle = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ, false, targetProcess.Id);
            IntPtr loadLibraryAddr = GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA");
            IntPtr allocMemAddress = VirtualAllocEx(procHandle, IntPtr.Zero, (uint)((dllName.Length + 1) * Marshal.SizeOf(typeof(char))), MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
            UIntPtr bytesWritten;
            WriteProcessMemory(procHandle, allocMemAddress, Encoding.Default.GetBytes(dllName), (uint)((dllName.Length + 1) * Marshal.SizeOf(typeof(char))), out bytesWritten);
            CreateRemoteThread(procHandle, IntPtr.Zero, 0, loadLibraryAddr, allocMemAddress, 0, IntPtr.Zero);
            return 0;
        }

        public static void Execute()
        {
            string rawDLL = String.Empty;
            if (is64BitOperatingSystem)
            {
                rawDLL = Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), "DLL.dll");
            }
            else
            {
                rawDLL = Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), "DLL.dll");
            }
            // Execution of injection
            Process proc = Process.GetProcessesByName("mspaint")[0];
            Injection.inject(rawDLL, proc);
            isInjected = true;
        }
        public static Boolean isInjectedAlready()
        {
            if (isInjected)
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        public static bool InternalCheckIsWow64()
        {
            if ((Environment.OSVersion.Version.Major == 5 && Environment.OSVersion.Version.Minor >= 1) ||
                Environment.OSVersion.Version.Major >= 6)
            {
                using (Process p = Process.GetCurrentProcess())
                {
                    bool retVal;
                    if (!IsWow64Process(p.Handle, out retVal))
                    {
                        return false;
                    }
                    return retVal;
                }
            }
            else
            {
                return false;
            }
        }
    }

    public class Program
    {
        public static void Main()
        {
            Injection.Execute();
        }
    }
}

Профит

upload_2016-12-25_3-20-44.png

DLL Hijacking
Это мы взглянули в целом на технику DLL Injection, а теперь же давайте посмотрим на DLL Hijacking.
Идея этой уязвимости заключается в особенности организации работы подхвата dll’ок. Совершенно логично, что в первую очередь при добавлении библиотеки, маперы ищут её в своей директории, и только потом в заданных настройках ОС. Таким образом мы получаем, что если мы знаем имя библиотеки, подгружаемой в утилиту, а так же существует собственно сама уязвимость dll hijacking’a, мы можем подложить нашу dll с нагрузкой в корень с утилитой.

Я перепишу код метода Main, который на на этот раз, будет архи простым, но дергать метод из другой dll библиотеки. Напишем же её.

Код:

using System.Windows.Forms;

namespace DllValid
{
    public class Validation
    {
        public void GetMessage()
        {
            MessageBox.Show("Я нормальная библиотека");
        }
 
    }
}

А вот код метода Main, когда мы подключим нашу библиотеку.

upload_2016-12-25_3-39-57.png

Код:

using DllValid;

namespace alphabotcsharp
{
    public class Program
    {
        public static void Main()
        {
            Validation message = new Validation();
            message.GetMessage();
        }
    }
}

Убедимся, что всё работает.

upload_2016-12-25_3-44-36.png

Как мы видим, на этот раз, код оказался до боли простой, но метод ссылается на другой путь. Теперь возьмем dll из старого проекта и кинем в наш, переназвав его соответственно. Получаем ошибку о том, что не соотвествует манифест. Здесь нам поможет в исследовании утилитка dotPeek.

upload_2016-12-25_3-51-7.png

Загрузим в утилиту наш билд:

upload_2016-12-25_3-49-46.png

Как мы видим, утилита, с помощью радостей рефлексии, выдергивает манифесты сборки, классы, методы и многое другое. Однако если у нас не .Net приложение то можно использовать утилиту ProcessExplorer.exe, которая показывает сборки используемые в проекте. Понятное дело, что если мы перепишем dll с таким же namespace’om, именем класса и метода, то всё отработает.

Но это не интересно. Всё таки нам нужно вызвать наш метод, для этого вместо DllMain воспользуемся методом IClassFactory::CreateInstance

В результате перепишем метод DLLMain на CreateInstance и снова кладем её в нашу директорию с утилитой.

Профит: Хотя мы и получаем в результате ошибку, наш код всё равно выполняется, так как инстанс создается раньше, чем система проверяет манифест.

upload_2016-12-25_4-11-49.png

На этом всё, всем спасибо. :)

P.S. Те кто ждут статью про ботнет, обязательно дождутся, в следующей статье добавим еще две команды, отрефакторим весь предыдущий код и будем запускаться с повышенными привилегиями по запросу (а в некоторых случаях и без него).

Как Создают Инжекторы?

Полезные Инструкции


Часто ли вы используете инжектор для внедрения файлов? Каждый день? А вы знали что первые инжекторы DLL файлов появлялись в открытом доступе примерно в 2010 году, это больше 11 лет назад. В то время, загрузить эту программу было крайне сложно, так как их разработка только начиналась, и они были созданы в малом количестве, к тому же просто так делиться ценным скриптом никто не хотел. В наше время скачать Инжекторы можно совершенно бесплатно и без каких либо проблем, сегодня их существует огромное количество для разных игр и не только.

Что такое инжектор?

Для начала, давайте вспомним, что такое Injector? Инжектор — это не сложная программа для внедрения в запущенное приложение динамических .dll файлов, добавляя свои или изменяя готовые данные из оперативной памяти запущеного процесса. Чаще всего эта утилита используется для онлайн игр, так как для Offline развлечений изменить параметры проще. В основном с помощью инъекции, внедряют разные читы.

Как происходит инъекция?

  1. Запускается приложение, настройки которого будут изменяться путем внедрения DLL файла.
  2. Запущенный процесс, чаще всего игра, сворачивается и запускается инжектор.
  3. В скрипте для внедрения, выбирается нужная библиотека файла с расширением .dll, а также указывается путь к папке с .exe файлом запуска игры, в которую нужно внедрять скрипт.
  4. Нажимаем кнопку «Инжектить», после этого можно развернуть развлечение и увидеть изменения.

Как создают инжекторы?

Для создания простой программы инъекции, необходим компонент Visual Studio, в которой разработчик должен написать свой код для будущего скрипта. Вот пример кода для самого простого инжектора:

#include <Windows.h>
#include <TlHelp32.h>
#include <iostream>
#include <io.h>

DWORD GetProcessByName(char * process_name)
{
    HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    PROCESSENTRY32 process;
    DWORD proc_id = 0;
    if (Process32First(snapshot, &process))
    {
        while (Process32Next(snapshot, &process))
        {
            if (_stricmp(process.szExeFile, process_name) == 0)
            {
                proc_id = process.th32ProcessID;
                break;
            }
        }
    }
    CloseHandle(snapshot);
    return proc_id;
}

bool FileExist(char* name)
{
    return _access(name, 0) != -1;
}

bool Inject(DWORD pID, char* path)
{
    HANDLE proc_handle;
    LPVOID RemoteString;
    LPVOID LoadLibAddy;
    if (pID == 0)
        return false;
    proc_handle = OpenProcess(PROCESS_ALL_ACCESS, false, pID);
    if (proc_handle == 0)
        return false;
    LoadLibAddy = (LPVOID)GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA");
    RemoteString = VirtualAllocEx(proc_handle, NULL, strlen(path), MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
    WriteProcessMemory(proc_handle, RemoteString, path, strlen(path), NULL);
    CreateRemoteThread(proc_handle, NULL, NULL, (LPTHREAD_START_ROUTINE)LoadLibAddy, RemoteString, NULL, NULL);
    CloseHandle(proc_handle);
    return true;
}

При компиляции этого простого кода, в настройках указывается многобайтовая кодировка, затем происходит протект готового файла для меньшей вероятности обнаружения антивирусами. На этом наш простой и рабочий скрипт успешно создан, осталось лишь им воспользоваться и попробовать внедрить какой-либо DLL в запущенное приложение.

Понравилась статья? Поделить с друзьями:
  • Как написать инди рок
  • Как написать индекс на пустом конверте
  • Как написать индекс на айфоне
  • Как написать индекс казахстана
  • Как написать индеец правильно