Folgende Warnungen sind aufgetreten:
Warning [2] preg_match_all(): The /e modifier is no longer supported, use preg_replace_callback instead - Line: 1007 - File: inc/highlighter.php PHP 7.4.33 (Linux)
File Line Function
[PHP]   errorHandler->error
/inc/highlighter.php 1007 preg_match_all
/inc/highlighter.php 112 generic_highlight
/inc/highlighter.php 48 generic_c_highlight
/inc/highlighter.php 53 cpp_highlight
/inc/plugins/coolcode.php 133 c_highlight
/inc/plugins/coolcode.php 61 coolcode_run
/inc/class_plugins.php 139 coolcode_end
/inc/class_parser.php 232 pluginSystem->run_hooks
/printthread.php 184 postParser->parse_message
Warning [2] Invalid argument supplied for foreach() - Line: 1008 - File: inc/highlighter.php PHP 7.4.33 (Linux)
File Line Function
/inc/highlighter.php 1008 errorHandler->error
/inc/highlighter.php 112 generic_highlight
/inc/highlighter.php 48 generic_c_highlight
/inc/highlighter.php 53 cpp_highlight
/inc/plugins/coolcode.php 133 c_highlight
/inc/plugins/coolcode.php 61 coolcode_run
/inc/class_plugins.php 139 coolcode_end
/inc/class_parser.php 232 pluginSystem->run_hooks
/printthread.php 184 postParser->parse_message



Home of Gamehacking - Archiv
[C++]Funktion um dynamisch eine CodeCave zu schreiben - Druckversion

+- Home of Gamehacking - Archiv (http://archiv-homeofgamehacking.de)
+-- Forum: Coding (http://archiv-homeofgamehacking.de/forumdisplay.php?fid=15)
+--- Forum: C, C#, C++, Visual C++ (http://archiv-homeofgamehacking.de/forumdisplay.php?fid=18)
+--- Thema: [C++]Funktion um dynamisch eine CodeCave zu schreiben (/showthread.php?tid=842)



[C++]Funktion um dynamisch eine CodeCave zu schreiben - Acubra - 11.01.2012

Hey,
hier mal meine Funktion zum Schreiben einer CodeCave (inklusive Jump hin und zurück), wobei der Speicher dafür per VirtualAllocEx dynamisch alloziiert wird.
Dies ist wohl die komplexeste und wichtigste Funktion meiner Base.

C Code
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
//////////////////////////////////////////////////////////////////////////
//WriteAllocCave
//This function will write a codecave to an allocated memory address. Then it will write a jump to the cave at a specified address.
//Furthermore you need to pass the offset relative to your base address to the function.
//Function will return 1 if everything went correctly. If not it will show you an error and return 0.
//////////////////////////////////////////////////////////////////////////
int WriteAllocCave(LPCWSTR szProcessName, LPCWSTR szModuleName, DWORD dwOffset, BYTE szOrigCode[], int nOrigCode, BYTE szCaveCode[], int nCaveCode)
{
	HANDLE hProcess; //Process handle.
	DWORD BaseAddress, lpAddress, dwOldProtect, nNops, lpBackAddress;
	LPVOID lpCaveAddress;//BaseAddress of the module and the real address we want to know.
	char* BytesRead[255]; //Buffer
	DWORD szJumpBytes[9] = {0x0E9, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90};
	BYTE szJumpBack[5] = {0x0E9, 0x90, 0x90, 0x90, 0x90};

	hProcess = GetProcessHandle(szProcessName); //Get the process handle for WPM/RPM.
	if (hProcess == 0)
	{
		MessageBox(NULL, _T("Couldn't get process handle!"), szErrorTitle, NULL);
		return 0;
	}
	BaseAddress = GetModuleBaseAddress(szProcessName, szModuleName); //Get the base address of the specific module.
	if (BaseAddress == 0)
	{
		MessageBox(NULL, _T("Couldn't get module base address!"), szErrorTitle, NULL);
		return 0;
	}

	lpAddress = (DWORD)BaseAddress + dwOffset; //Calculate real address.

	//First we need to allocate memory. Calculate the size of the needed cave
	int iCaveSize = nCaveCode + 5; //+5 because a 5 Bytes jump back after the cave
	//Allocate memory.
	if((lpCaveAddress = VirtualAllocEx(hProcess, 0, iCaveSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE)) == 0)
	{
		//Function failed.
		MessageBox(NULL, _T("Failed to allocate memory!"), szErrorTitle, NULL);
		return 0;
	}
	//Calculate Bytes for the jump to the code cave.
	void* var = &szJumpBytes; //Variable to store the address of the szJumpBytes variable
	__asm //Credits to Specid from DVT for the general idea
	{
		pushad
			mov ebx, lpCaveAddress
			mov ecx, lpAddress
			add ecx, 5
			sub ebx, ecx ;//Calculate the distance.
			mov edx, ebx ;//Store the distance
			shr edx, 16
			mov eax, var
			mov byte ptr [eax+1], bl ;//Write the calculated bytes into the variable.
			mov byte ptr [eax+2], bh
			mov byte ptr [eax+3], dl
			mov byte ptr [eax+4], dh 
			;//Now we have to calculate the needed NOPs (0x90).
			mov ebx, nOrigCode ;//Number of bytes the original code has.
			sub ebx, 5 ;//Decrease this number by 5, because that's the bytes for the jump.
			mov nNops, ebx ;//Number of NOPs we have to write.
			mov edx, 4
			xor ebx, ebx
		start:
			cmp nNops, ebx
			je End
				INC edx
				INC ebx
				mov byte ptr [eax+edx], 144 ;//144d == 90h == NOP
			jmp start

		End:
		popad
	}
	//Read code and compare it. If it's szOrigCode, then we need to write our jump to the cave + the cave code. If it's the jump to the 
	//cave, we need to write the original code (user deactivated trainer).
	//If it's neither one of these two, then the user has probably a wrong version.
	//First VirtualProtectEx to make the code read/writeable.
	if (VirtualProtectEx(hProcess, (LPVOID)lpAddress, nOrigCode, PAGE_EXECUTE_READWRITE, &dwOldProtect) == 0)
	{
		MessageBox(NULL, _T("VirtualProtectEx failed!"), szErrorTitle, NULL);
		return 0;
	}
	//Now ReadProcessMemory and the byte comparison.
	if(ReadProcessMemory(hProcess, (LPVOID)lpAddress, (LPVOID)BytesRead, nOrigCode, 0) == 0)
	{
		MessageBox(NULL, _T("ReadProcessMemory failed!"), szErrorTitle, NULL);
		return 0;
	}

	//Compare original bytes with those standing in memory.
	if(memcmp((const void*)BytesRead, szOrigCode, nOrigCode) == 0) //Bytes match.
	{
		//We got the original bytes standing in memory, so we write the cave code now.
		if((WriteProcessMemory(hProcess, (LPVOID)lpCaveAddress, (LPCVOID)szCaveCode, nCaveCode, 0)) == 0)
		{
			//Oh noes, WPM error.
			MessageBox(NULL, _T("Failed to write to process memory.."), szErrorTitle, NULL);				return 0;
		}
		else
		{	//Now we write the jump back to the original code. (after the cave code)
			lpBackAddress = (DWORD)lpCaveAddress + nCaveCode;
			//Calculate bytes for the jump back to the original code.
			var = &szJumpBack;
			__asm
			{
				pushad ;//Save register
					mov ebx, lpAddress
					add ebx, 5 ;//Add 5 to lpAddress since there are standing our bytes for the jump to the cave
					mov ecx, lpBackAddress
				    add ecx, 5
					sub ebx, ecx
					mov edx, ebx ;//Store the distance
					shr edx, 16
					mov eax, var
					mov byte ptr [eax+1], bl ;//Write the calculated bytes into the variable.
					mov byte ptr [eax+2], bh
					mov byte ptr [eax+3], dl
					mov byte ptr [eax+4], dh 
				popad ;//Restore register
			}
			//Write jump to the original code
			if((WriteProcessMemory(hProcess, (LPVOID)lpBackAddress, (LPCVOID)szJumpBack, sizeof szJumpBack, 0)) == 0)
			{
				//Oh noes, WPM error.
				MessageBox(NULL, _T("Failed to write to process memory.."), szErrorTitle, NULL);
				return 0;
			}
			else
			{
				//Write jump to our cave == finish cheat.
				if((WriteProcessMemory(hProcess, (LPVOID)lpAddress, (LPCVOID)szJumpBytes, nOrigCode, 0)) == 0)
				{
					//Oh noes, WPM error.
					MessageBox(NULL, _T("Failed to write to process memory.."), szErrorTitle, NULL);
					return 0;
				}
				else //Everything went fine.
				{
					Beep(0x1000,200); //Activated sound.
					return 1;
				}
			}
		}
	}
	//First compare (original bytes) didn't succeed, so we check now for modified bytes (jump to cave).
	//Compare just the first Byte (weather there is 0E9h or not).
	else if (memcmp((const void*)BytesRead, szJumpBytes, 1) == 0) //Bytes match.
	{
		//We got the jump bytes(to the cave)standing in memory. So the user wants to deactivate the option now. Therefore we need to write
		//the original bytes.
		if ((WriteProcessMemory(hProcess, (LPVOID)lpAddress, (LPCVOID)szOrigCode, nOrigCode, 0)) == 0)
		{ 
			//Oh noes, WPM error.
			MessageBox(NULL, _T("Failed to write to process memory.."), szErrorTitle, NULL);
			return 0;
		}
		else //Everything went fine.
		{
			Beep(0x500,200); //Deactivated sound.
			return 1;
		}
	}
	else
	{
		//Neither modified bytes nor original bytes found. So the user has a wrong/currupted version.
		MessageBox(NULL, _T("You have the wrong gameversion!"), szErrorTitle, NULL);
		return 0;
	}

	return 0;
}




RE: [C++]Funktion um dynamisch eine CodeCave zu schreiben - Disconnect - 26.02.2012

Warum schreibst du

Code:
if ((WriteProcessMemory(hProcess, (LPVOID)lpAddress, (LPCVOID)szOrigCode, nOrigCode, 0)) == 0)

und nicht gleich

Code:
if (WriteProcessMemory(hProcess, (LPVOID)lpAddress, (LPCVOID)szOrigCode, nOrigCode, 0) == 0)

?


RE: [C++]Funktion um dynamisch eine CodeCave zu schreiben - Acubra - 26.02.2012

Hey,
da hab ich wohl zwei Klammern zuviel geschrieben :blush: Du hast Recht, man kanns auch mit nur einer Klammer schreiben. Sollte aber nicht weiter stören.


RE: [C++]Funktion um dynamisch eine CodeCave zu schreiben - Disconnect - 26.02.2012

(26.02.2012, 17:37)Acubra schrieb: Hey,
da hab ich wohl zwei Klammern zuviel geschrieben :blush: Du hast Recht, man kanns auch mit nur einer Klammer schreiben. Sollte aber nicht weiter stören.

Eigentlich sollte man auch statt den C-Casts C++-Casts verwenden.
Naja Haarspalterei Wink