Quick critique: ARMA Series scripting language.

Alright, fuck it.

People know me, I mean, I don’t consider myself a complete fool when it comes to programming and I think there’s probably a lot of people who don’t really consider me that shabby either.
I am however completely incapable of developing ARMA3 missions. It’s just not possible. I tried.

Here’s the problem: The game’s scripting engine is god awful. Nobody says this enough, if you go on the BIS forums and try to state this openly you will be berated by fanboys who have no programming background and have very likely never touched the sqf “language” in their life. I’m going to go point-by-point here and explain what went wrong with this clusterfuck of a language. Read more

How I hacked Max Payne 3

Random information: This post was written months before I published it, back in November 2012. I didn’t publish it because I was angry at the time and it felt like a rant. It still is a rant, but I feel like it should be published anyway.

Just a short post, maybe it’ll help people hacking RAGE engine games since Rockstar took it upon themselves to be gigantic assholes to the modding community. I’m going to show them how you hack their games, online. Yes. This doesn’t stop me, the person who will ruin your fun in online games. This kills the modding community. Thanks a lot Rockstar games, you are the biggest pieces of scumbag shit in the sandbox gaming arena today. Read more

D Module Injector

I wrote a D module injector! It’s coded in C++, but it works with the latest DMD2.

Basically, here’s a rundown of the problem I was facing. You can’t use CreateRemoteThread to invoke LoadLibrary to load a D module into a foreign (or local, for that matter, seriously try LoadLibrary with CreateThread in a C++ application) process without it crashing. For some reason or another you must load the module in the primary process thread. This is what this hook does. I suspend the “main” thread, switch out EIP for my own (allocated code cave) and JMP back to the original code.

This has only been tested with “Hitman: Absolution” but give it a shot on your process and let me know how it goes! I included the source code and binary for the C++ program in the download below. Enjoy.

Download174 downloads

Hitman: Absolution Trainer Version 2

Version 2 of my trainer is released now!

Hitman Absolution Money Hack

Super money!

Download1663 downloads

Read more

Assembly equivalents and anti-hashing tricks

Well I made this project a while back and I just sort of never did anything with it.

I absolutely realize this isn’t “true” polymorphism, but, if you’re looking to change your module hash or change the hashes of code pages (such was the case with VAC2, maybe VAC3?) this will help you out.

It probably won’t do very much good against pure sig scanning, and it was mostly for fun when I made it just to see how far I could push it.

I called it “AgentFred” (“A scanner darkly” reference, lel) and what it does, basically, is convert opcodes to alternative opcodes of the same length. This means you don’t have to redo all the relative junk. It might be helpful in actual polymorphic engines, too. However, this isn’t reversible. I’ll show you a list of what it does, then I’ll explain it only goes one way. It doesn’t convert opcodes interchangeably (for example, sub esp, 0×2 -> dec esp; dec esp; is possible but it will not do dec esp; dec esp; -> sub esp, 0×2, maybe with some work it could be made to do stuff like this, but right now it does not)

 C++ |  copy code |? 
001
void obfuscateOpcode( UCHAR* opcodeAddress, unsigned long opcodeLength )
002
{
003
	MEMORY_BASIC_INFORMATION mbi;
004
 
005
	VirtualQuery( opcodeAddress, &mbi, sizeof( mbi ) );
006
 
007
	VirtualProtect( mbi.BaseAddress, mbi.RegionSize, PAGE_EXECUTE_READWRITE, &mbi.Protect );
008
 
009
	if( opcodeLength == 1 )
010
	{
011
		if( opcodeAddress[0] == 0xC3 && opcodeAddress[1] == 0xCC && opcodeAddress[2] == 0xCC )
012
		{
013
			// retn -> retn (0)
014
 
015
			opcodeAddress[0] = 0xC2;
016
			opcodeAddress[1] = 0x00;
017
			opcodeAddress[2] = 0x00;
018
 
019
			if(printOutput) printf( "retn -> retn (0) [0x%X]\n", opcodeAddress );
020
		}
021
		else if( opcodeAddress[0] == 0xCC && opcodeLength == 1 )
022
		{
023
			srand( GetCurrentProcessId() * GetTickCount() );
024
 
025
			opcodeAddress[0] = rand() % 0xFF;
026
 
027
			if(printOutput) printf( "CC -> rand [0x%X]\n", opcodeAddress );
028
		}
029
	}
030
	else if( opcodeLength == 2 )
031
	{
032
		if( opcodeAddress[0] == 0xD8 && ( opcodeAddress[1] >= 0xD8 && opcodeAddress[1] <= 0xDF ) )
033
		{
034
			unsigned char asm_reg = opcodeAddress[1] - 0xD8;
035
 
036
			// fcomp st might be broken for 0, again.
037
 
038
			if( rand() % 2 )
039
			{
040
				opcodeAddress[0] = 0xDE; // fcomp st -> fcomp3 st (Identical in IDA)
041
				opcodeAddress[1] = 0xD0 + asm_reg;
042
 
043
				if(printOutput) printf( "fcomp st -> fcomp3 st [0x%X]\n", opcodeAddress );
044
			}
045
			else
046
			{
047
				opcodeAddress[0] = 0xDC; // fcomp st -> fcomp5 st
048
 
049
				if(printOutput) printf( "fcomp st -> fcomp5 st [0x%X]\n", opcodeAddress );
050
			}
051
		}
052
		else if( opcodeAddress[0] == 0xD8 && ( opcodeAddress[1] >= 0xD0 && opcodeAddress[1] <= 0xD7 ) )
053
		{
054
			opcodeAddress[0] = 0xDC; // fcom st -> fcom2 st (Identical in IDA)
055
 
056
			if(printOutput) printf( "fcom st -> fcom2 st [0x%X]\n", opcodeAddress );
057
		}
058
		else if( opcodeAddress[0] == 0xDD && ( opcodeAddress[1] >= 0xD8 && opcodeAddress[1] <= 0xDF ) )
059
		{
060
			unsigned char asm_reg = opcodeAddress[1] - 0xD8;
061
 
062
			// fstp st (0) might be broken, I'm not even entirely sure
063
 
064
			switch( rand() % 3 )
065
			{
066
			case 0:
067
				opcodeAddress[0] = 0xD9; // fstp st -> fstp1 st
068
				if(printOutput) printf( "fstp st -> fstp1 st st [0x%X]\n", opcodeAddress );
069
				break;
070
			case 1:
071
				opcodeAddress[0] = 0xDF; // fstp st -> fstp8 st
072
				opcodeAddress[1] = 0xD0 + asm_reg;
073
				if(printOutput) printf( "fstp st -> fstp8 st [0x%X]\n", opcodeAddress );
074
				break;
075
			case 2:
076
				opcodeAddress[0] = 0xDF; // fstp st -> fstp9 st
077
				if(printOutput) printf( "fstp st -> fstp9 st [0x%X]\n", opcodeAddress );
078
				break;
079
			}
080
		}
081
		else if( opcodeAddress[0] == 0xD9 && ( opcodeAddress[1] >= 0xC8 && opcodeAddress[1] <= 0xCF ) )
082
		{
083
			// FXCH ST(i)
084
 
085
			opcodeAddress[0] = 0xDF; // FXCH ST(i) -> FXCH7 ST(i)
086
 
087
			if(printOutput) printf( "FXCH ST(i) -> FXCH7 ST(i) [0x%X]\n", opcodeAddress );
088
		}
089
	}
090
	else if( opcodeLength == 3 )
091
	{
092
		// add reg, num -> inc (num), recursive, nop
093
 
094
		if( opcodeAddress[0] == 0x83 && ( opcodeAddress[1] >= 0xC0 && opcodeAddress[1] <= 0xC7 ) && opcodeAddress[2] <= 3 )
095
		{
096
			unsigned char asm_reg = opcodeAddress[1] - 0xC0;
097
			unsigned char asm_add = opcodeAddress[2];
098
 
099
			for( unsigned char i = 0; i < 3; i++ )
100
			{
101
				if( i >= asm_add )
102
				{
103
					opcodeAddress[i] = 0x90;
104
 
105
					continue;
106
				}
107
 
108
				opcodeAddress[i] = 0x40 + asm_reg;
109
			}
110
 
111
			if(printOutput) printf( "add reg, num -> inc (num), recursive, nop [0x%X]\n", opcodeAddress );
112
		}
113
 
114
		// sub reg, num -> dec (num), recursive, nop
115
 
116
		else if( opcodeAddress[0] == 0x83 && ( opcodeAddress[1] >= 0xE8 && opcodeAddress[1] <= 0xEF ) && opcodeAddress[2] <= 3 )
117
		{
118
			unsigned char asm_reg = opcodeAddress[1] - 0xE8;
119
			unsigned char asm_sub = opcodeAddress[2];
120
 
121
			for( unsigned char i = 0; i < 3; i++ )
122
			{
123
				if( i >= asm_sub )
124
				{
125
					opcodeAddress[i] = 0x90;
126
 
127
					continue;
128
				}
129
 
130
				opcodeAddress[i] = 0x48 + asm_reg;
131
			}
132
 
133
			if(printOutput) printf( "sub reg, num -> dec (num), recursive, nop [0x%X]\n", opcodeAddress );
134
		}
135
	}
136
	else if( opcodeLength == 5 )
137
	{
138
		// mov reg, num -> xor reg, reg; xor reg, num
139
 
140
		if( opcodeAddress[0] >= 0xB8 && opcodeAddress[0] <= 0xBF )
141
		{
142
			DWORD lengthToMov = *( DWORD* )( opcodeAddress + 1 );
143
 
144
			UCHAR asm_reg = opcodeAddress[0] - 0xB8;
145
 
146
			// 0xF or below
147
			if( lengthToMov < 16 )
148
			{
149
				opcodeAddress[0] = 0x33;
150
				opcodeAddress[1] = 0xC0 + ( asm_reg * 9 );
151
				opcodeAddress[2] = 0x83;
152
				opcodeAddress[3] = 0xF0 + asm_reg;
153
				opcodeAddress[4] = ( unsigned char ) lengthToMov;
154
 
155
				if(printOutput) printf( "mov reg, num -> xor reg, reg; xor reg, num (0) [0x%X]\n", opcodeAddress );
156
			}
157
			else if( lengthToMov <= 0xFF && asm_reg == 0 )
158
			{
159
				// xor eax, eax
160
				opcodeAddress[0] = 0x33;
161
				opcodeAddress[1] = 0xC0 + ( asm_reg * 9 );
162
 
163
				// add al, num (can probably be used for bl, cl too)
164
				opcodeAddress[2] = 0x04;
165
				opcodeAddress[3] = ( unsigned char ) lengthToMov;
166
 
167
				if(printOutput) printf( "mov eax, num -> xor eax, eax, add al, num [0x%X]\n", opcodeAddress );
168
			}
169
		}
170
	}
171
 
172
	VirtualProtect( mbi.BaseAddress, mbi.RegionSize, mbi.Protect, NULL );
173
}

There’s a few major problems with this:

  • For it to work out well you’ll probably need to bloat up your executable. Reason being that most of the time the compiler will choose a method which is bigger, but faster with different compiler settings.
  • Quirks like these aren’t very common. Sometimes you can run entire sections through and hit nothing.
  • If it’s hooked up to some kind of randomization engine and it was able to run both ways (convert to < - > from opcodes) it might be able to obfuscate more things, but still not a ton.

Here’s some positives:

  • It only requires an opcode length disassembler
  • You don’t have to fix relative opcodes since there’s no code being shifted around.
  • Fairly easy to implement into any existing project without much overhead

All in all this boils down to nothing but a bunch of free time I had a while back, and I decided to publish it because it’s kinda neat information but it’s absolutely not very useful practically. If you want true polymorphism, better get working with an actual disassembler, and learn how to fix those pesky relative opcodes.

Hacking with D!

I took some (short) time out of my day to mess around with the D programming language. There’s no _ReturnAddress compiler intrinsic I’m aware of, and casting for this kind of stuff is kind of strange so I thought I’d post about it.

D Programming Language

D Programming language by digitalmars – Weird and useful after all.

Read more

How VTable hooking works, and detecting it!

I’m going to quickly explain how a “virtual table”, or “VTable” for short, works (at least in windows, although you can assume it’s similar for other operating systems). I’m also going to dedicate a small section to detecting when these vtables are modified!

First, I’m going to need to explain how structs work (in memory), when a struct is made

 C++ |  copy code |? 
1
struct this_is_example_s
2
{
3
	DWORD member1;
4
	DWORD member2;
5
};

and you, let’s say, allocate a global variable

 C++ |  copy code |? 
1
this_is_example_s* g_pExampleData = new this_is_example_s;

the struct layout in memory looks like this

 C++ |  copy code |? 
1
struct this_is_example_s
2
{
3
	DWORD member1; // this is struct_ref + 0000
4
	DWORD member2; // this is struct_ref + 0004 (0000 + sizeof(DWORD) = here), the next member would be at 0008
5
};
Read more

Invoking scripts in ARMA2′s script engine

This is mostly just me testing my WordPress -> Twitter plugin, but! but! I have something neat to share, too.


Note: This video is super old and has really horrible music

Read more

Steam GameOverlayUI hooking and microsoft rage!

Alright, before I start this post I’m going to rant about something. Microsoft needs to cut the bullshit and implement a global, system-wide rendering method for overlays. Fraps, Steam, XFire, Raptr, Origin, Teamspeak and a ton of other gaming related applications have to hook into games, as it stands, to render what they want. This is unacceptable. Steam’s GameOverlayUI overlay currently has hooks on DirectDraw, OpenGL, DirectX 8, 9, 10, 11 (and it hooks various methods of initializing these interfaces, so CreateDXGIFactory, CreateDXGIFactory1, Direct3DCreate9, Direct3DCreate9Ex, DirectDrawCreate, DirectDrawCreateEx)… this is… insane. Surely, somebody must realize this besides myself. I admire the developer of the overlay (assuming it’s still just one guy) and I’ve actually mailed him before telling him it’s very neat, but nobody should have to do this. Just talking about it is getting me angrier. Microsoft, please solve this problem. You can even make a function to retrieve all the overlays so cheaters aren’t a problem, or something, I don’t know but please do something. (Yes, I’m fully aware nobody from microsoft will read this, I’ll send an email bitching at them that nobody will read later)

Moving on, I have reversed the GameOverlayUI again as I have done in the past, I’ve released an update and I wanted to post about it.

with Steam's GameOverlayUI

Rendering in Payday with GameOverlayUI

Read more

WarZ Packet exploit uncovered

A while back I posted a video on youtube entitled “WarZ Bringer of Death”, you can watch it below

Lots of people have asked me what’s going on in this video and I’ll tell you: I’m killing them with code. How is that supposed to be possible? Doesn’t a large amount of that processing occur on the server? Well, yes it does. The exploit does not depend upon me actually telling the server I killed anyone, but rather, telling the server I’m them. Once I tell the server I am them, and I send a fall damage packet with a lot of extra damage (about the amount that would kill any living being in the game) it will inform them that they are in fact dead.

Allow me to explain: WarZ packet structures work like this
[BYTE (Event ID)][WORD (Network ID)][EVENT-ID-SPECIFIC-DATA-HERE] Read more