loading a DLL from memory

Started by
14 comments, last by caesar4 20 years ago
quote:Original post by caesar4
if i write it as a temp file, it could be cracked

EDIT: it would take the best cracker to crack it if it''s loaded from memory, so the piracy rate should drop a thousand-fold


Assuming it is YOUR .dll, you have the source code - so why use a .dll at all then? Make the source part of your main .exe.

Maybe I don''t understand why you''re wanting to do this. What do you mean someone can "crack" your .dll? Do you mean figure out how to use its exported functions?
Brianmiserere nostri Domine miserere nostri
Advertisement
by subprojecting my game project (different types of components in different dlls) it is easier to debug.
as for the load, i am talking hypothetically, such protection is only on my TODO list
if i can get it done, u can be sure that my game would be one of the hardest to pirate/crack

Edit: you're right, if they wonna crack my game, they will. but the purpose of this is to make it extremely hard to crack

[edited by - caesar4 on April 12, 2004 7:41:17 PM]
Cartman's definition of sexual harrasement:"When you are trying to have intercourse with a lady friend, and some other guy comes up and tickles your balls from behind"(watch South Park, it rocks)
(1) Who''s gonna want to crack your game?
(2) If they want to crack your game, they will crack your game
Of course it''s possible by doing what the Win32 loader does. Assuming the DLL doesn''t require initialization or relocation, all you have to do is implement GetProcAddress. There''s no magic here - see the PE file specs.
Some slightly obfuscated code:
;_______________________________________________________;;; > ebx -> DLL ^ DLL_BASE_KEY (crash+burn if invalid); > edx = function name [8:5] ^ FUNC_NAME_KEY; < eax -> function address ^ FUNC_ADDR_KEY; < ebx -> DLL; < flags: positive addition; x ecx edx esi edi;_______________________________________________________;;get_proc_address:	; twiddle params around and zero edi	xchg		eax, edx			; eax = name, edx = org eax	cdq						; name is ASCII (< 0x80) => edx = 0	xchg		eax, edx			; eax = 0, edx = name	xor		edx, FUNC_NAME_KEY		; decrypt name	xchg		eax, edi			; eax = org edi, edi = 0	xor		ebx, DLL_BASE_KEY	xchg		eax, ecx			; NOP (eax = org ecx, ecx = org edi)	; esi -> export dir	mov		eax, [ebx+0x3c]			; PE header RVA	mov		esi, [ebx+eax+0x78]		; export dir RVA	add		esi, ebx			; -> export dir	; scan name table; overrun if not found. put index in edi	add		esi, byte 0x20	lodsd						; import name array RVA (exp_dir+0x20)find_name_loop:	mov		ecx, [ebx+eax]			; import name RVA	inc		edi	add		eax, byte 4	cmp		[ebx+ecx+5], edx		; compare second dword of name	jne		find_name_loop	cdq						; hide no longer needed edx	; convert index to ordinal	lodsd						; ordinal table RVA (exp_dir+0x24)	add		eax, ebx	movzx		edx, word [eax+edi*2-2]		; ordinal	add		edx, [esi-0x28+0x10]		; re-based ordinal + 1 (exp_dir+0x10)	; return functions[ordinal]	mov		eax, [esi-0x28+0x1c]		; function table RVA (exp_dir+0x1c)	add		eax, ebx	mov		eax, [eax + edx*4 - 4]		; function	add		eax, ebx	xor		eax, FUNC_ADDR_KEY	ret 
E8 17 00 42 CE DC D2 DC E4 EA C4 40 CA DA C2 D8 CC 40 CA D0 E8 40E0 CA CA 96 5B B0 16 50 D7 D4 02 B2 02 86 E2 CD 21 58 48 79 F2 C3
that idea will NOT make your program much harder to crack.
actually, it''s a miniscule improvement.
For the sake of your project, u could define a new type of library, other than a dll. Call it what you want. The aim is to store the code image for each function in this "new dll".
To run the code, we load the file with function image(s), decrypt them if we have to, load it into some or other allocated memory, and run. I am not sure what type of memory allocation will be most optimal for running the code though. This you will have to read up on. There may also be other OS related issues with regards to memory management that are not immediately apparent. But asside from that, it can be done.

eg:
// Code segment that we want to run. Takes 2 parameters, adds
// them together, and returns the result.
// This would be our binary image, stored in a file, possibly
// encrypted.
DWORD AddTwoNumbersAndReturnResult_Image[32] =
{
0x0000000C, // Number of dwords to load from index 1.
0x83EC8B55, // Code starts.
0x565344EC,
0xBC7D8D57,
0x000011B9,
0xCCCCB800,
0xABF3CCCC,
0x0308458B,
0x45890C45,
0xFC458BFC,
0x8B5B5E5F,
0x08C25DE5,
0xFFFFFF00 // Code ends.
};
// Type definition for the function signature.
typedef INT (WINAPI* LPFUNC1)(INT,INT);
// First number in the array if the number of dwords to read
// in starting at index 1.
// Allocate memory for 12 dword values. The actual code image is
// 45 bytes.
DWORD* pdwCode = new DWORD[AddTwoNumbersAndReturnResult_Image[0]];
// Read in the code image we are going to run.
// NB: At this stage you may want to decrypt if you have done so.
for(UINT i=0;i<AddTwoNumbersAndReturnResult_Image[0];i++)
{
// Read 1 ahead since index 0 is reserved for number of dword
// values to read in.
pdwCode = AddTwoNumbersAndReturnResult_Image[i+1];
}
// Declare a function pointer from the typedef function signature
// we already have, and set it to point to our code image.
LPFUNC1 func1 = (LPFUNC1)pdwCode;
// Invoke the function, and get a return value.
n1 = func1(33,44);

PS: This will not work if u have recursive functions in ur app.

This topic is closed to new replies.

Advertisement