Log in

View Full Version : Dynamical byte manipulation of win32 executables


Harakiri
April 3rd, 2006, 14:04
Hello,

i dont know if this belongs to here but i figured those in-the-known could probably help.

Problem

I need to manipulate a precompiled win32.exe on a *nix system - the tools i have is just byte wise manipulation (no recompile, no c or anything). I want to dynamically change one data field (variable) of the win32 executeable - however the pitfall i currently face is that the data length i change is dynamically too.

Failed Theoretical Example

I created a simple hello world C program with a global var data as char. I preset the value of the variable as "hello world" - after compiling i open up a hex editor found the offset and could dynamically change the string - however i could only replace the string with a value that has the same length (and bit wise) size.

Therefor i made the variable static and said lets allocate 1000000000 bytes - well now my exe is always that big (tons of zeroes) so this aint an option too.

Question
Anyone has a good idea how i can dynamically change my data variable using byte manipulation ?


Background

The win32 exe will implement some sort of symmetric encryption - i will use one precompiled template for the exe file without any encrypted data - after that i will move it to a *nix server and dynamically manipulate the data of the encrypted content using Java. After the change a win32 user should be able to just execute this file and enter a password and will receive my dynamically generated data (decrypted).

goggles99
April 3rd, 2006, 15:05
you either need to append a new data section to the PE file, or expand a section. If you are adding a section on the *nix system, you may need to parse the executable from itself to find the section, get it's offset, and size...

Perhaps A better solutioin would be to add a new section at compile/link time. In the new section, have an UINT and a small byte array full of zeroes. Now enlarge this section (it should be the last section in your PE) on your *nix system and fill it with your data starting at the beginning of your byte array. Store the size of the bytes that you have placed into the new section into the UINT (or larger if necessary) variable.

Harakiri
April 3rd, 2006, 17:30
First, thank you for your reply and helpful insight.

add a new section at compile/link time ..[..]... have an UINT and a small byte array full of zeroes

Q: I've searched for some UINT references on google but i have to admit - im not a c expert. Could you supply a helpful page about the approach you are suggesting. (im using visual c for linking currently)

Store the size of the bytes that you have placed into the new section into the UINT (or larger if necessary) variable

Q: Given the above - i guess the UINT offset will be always at the same offset - right ? So i should have no trouble manipulating its value.

Thanks

goggles99
April 3rd, 2006, 18:38
oops, I forgot it will be written in java (which does not have unsigned integers) uint is "unsigned integer" in C++.

The "or larger if necessary" only meant that if the section size was larger than an integer can handle, you could use something larger EX:long. I only suggested the integer variable to store the size of the data for easy parsing and decryption.

This method may produce a limitation of sorts. I think that any given PE section cannot exceed 4 megabytes or something like that (I could be wrong about this). If your data will exceed that, you may just want to append the data to the end of the normal PE file. It should stull run fine. I don't think that it will be mapped into memory, but you can read it off of the disk. Perhaps just prepend and append your data with unique delimiters, have the executable read the entire file and search for these delimiters. Read and decrypt the data in-between them.

Harakiri
April 4th, 2006, 05:39
My data will exceed 4MB but probably not 10-20 MB...

To summarize your points :
(pseudo code)

win32exec.c
Code:

// start with some value
uint numBytes = 10;

// declare a field with my uint value
byte[] myData = new byte[numBytes];

// allocate memory
myData = malloc(numBytes * sizeof(byte));

// do decrypt stuff
[..]

------

manipulate.java

Code:

File f = new File("win32exec.exe");

// wrap a stream for reading the data
ByteArrayInputStream bis = new ByteArrayInputStream(f);

// let the stream read all data
while(bis.read() !=0)) {
}

byte[] myWin32Exec = bis.toByteArray();

// offset of the uint
int offSetNumSize = ??????;

// offset of the array
int offSetDataArray = ??????;

String randomString = "encrypted_data";

byte[] encryptedData = randomString.getBytes();

// assign new field length to offset of uint
myWin32Exec[offSetNumSize] = encryptedData.length;

// assign new data to array

for(int i=0; i < encryptedData.length; i++) {
myWin32Exec[offsetDataArray + i] = encryptedData[I];
}

// done save the file
[..]



Is that what you mean ? Or does the c program has to have static fields - how do i figure out the offsets of both the uint and mydata - can i just keep writing my encrypted_data from the beginning offset of mydata even if the file has no more bytes anyway ?

Thanks

Silver
April 5th, 2006, 05:21
I've never used java and I'm having trouble understanding what you want to do...

In your java code it looks like you're opening the win32 executable from disk (to all intents and purposes it's just a big data file to the java app), seeking through to position P and reading N bytes, then using N to find the offset to your data in the win32exe and reading that?

The problem with this is how you've coded the C app. The new and malloc statements allocate space on the heap at runtime, but your java code is expecting the space to be allocated inside the win32exe at build time, I think?

But in your first post you state:

Quote:
Therefor i made the variable static and said lets allocate 1000000000 bytes - well now my exe is always that big (tons of zeroes) so this aint an option too.


So I'm a bit confused about how you're trying to do this. You have some data of an unknown length which needs to be stored in the win32exe, but without preallocating any space in the win32exe for it? If you want to store it, it's going to take up room...

The only way I can see this working is if you add another PE section as goggles99 suggests. Append a PE section to your exe and put the static allocation in it - byte mydata[1], for example. Then when you need more than 1 byte stored in the win32exe simply write the extra bytes to the section (ie: emulate byte mydata[N]) and modify the PE header as appropriate.

0xf001
April 5th, 2006, 07:43
hi,

i am just thinking, what you probably need to do is to parse the pe header and "act accordingly". like extend the section for your data, and possibly manipulate the symbol table if you want to relocate the data.
I am not really into PE but do this on ELF which share a common base.

A possible better idea is - if you r/o this mem, to setup a pointer in your C prog to point to the data which is an appended section. If you need to have the size of it available, put it into your code - ie: size = 0xbeef;

Then in the process of adding the section, overwrite locate 0xbeef and change it to the size.

regards, 0xf001

Harakiri
April 5th, 2006, 08:35
Thanks for the responses guys..

Quote:
[Originally Posted by Silver]In your java code it looks like you're opening the win32 executable from disk (to all intents and purposes it's just a big data file to the java app), seeking through to position P and reading N bytes, then using N to find the offset to your data in the win32exe and reading that?


correct that was my initial idea together with using a static c variable

Quote:
[Originally Posted by Silver]
The problem with this is how you've coded the C app. The new and malloc statements allocate space on the heap at runtime, but your java code is expecting the space to be allocated inside the win32exe at build time, I think?

So I'm a bit confused about how you're trying to do this. You have some data of an unknown length which needs to be stored in the win32exe, but without preallocating any space in the win32exe for it? If you want to store it, it's going to take up room...



Yes i know it will take room - but my problem is that i do not know how i can modify that "room" for the data in the win32exe

Quote:
[Originally Posted by Silver]
The only way I can see this working is if you add another PE section as goggles99 suggests. Append a PE section to your exe and put the static allocation in it - byte mydata[1], for example. Then when you need more than 1 byte stored in the win32exe simply write the extra bytes to the section (ie: emulate byte mydata[N]) and modify the PE header as appropriate.


Ok, this is why i posted my pseudo code - i need a little bit more elaboration on this point.

How can i append a PE section to my exe in c ? Is this a linker option or already done at compile time ? I posted something like this :

byte mydata[numSize] - now you said initially numSize would be 1 - how should i declare this in a c program ?

just :

Code:
static byte mydata[1]


? And given that - i could just manipulate the data like i posted in my java program or is there another approach ?


Quote:
[Originally Posted by 0xf001]
A possible better idea is - if you r/o this mem, to setup a pointer in your C prog to point to the data which is an appended section. If you need to have the size of it available, put it into your code - ie: size = 0xbeef;


This is a nice idea, however my c knowledge is limited - do you mean i should just statically create a pointer which should always look inside the exe starting from offset 0xbeef ? right ?
And then again, in my java program i just append everything after 0xbeef with my data ?

Will this have any impact on the exe itself ? I mean i know the headers for an exe is important but isnt there some crc or can i just append random data to the end of the binary as long as i would like ?

0xf001
April 5th, 2006, 08:43
hi,

no i meant that is the size of your data. easy to find and so you know the offset where to patch your file where it references the size.

i am confused now what you want to achieve - it has not really to do with C - you told you have a C program. now does that use the size of your data? if yes - set that to 0xbeef or anything was what i meant - to help you figuring the offset of the access of the size initially, so your UX prog knows where to fill in the new size (could be multiple times, too i dont know your win C prog)

its like a help you do for you when compiling the C program on windows. only an idea.

well now to all else: look at exactly 1 thread before yours, it contains all you need (PE header docs)

cheers, 0xf001

Harakiri
April 5th, 2006, 09:10
Quote:
[Originally Posted by 0xf001]hi,

no i meant that is the size of your data. easy to find and so you know the offset where to patch your file where it references the size.

i am confused now what you want to achieve - it has not really to do with C - you told you have a C program. now does that use the size of your data? if yes - set that to 0xbeef or anything was what i meant - to help you figuring the offset of the access of the size initially, so your UX prog knows where to fill in the new size (could be multiple times, too i dont know your win C prog)


I will look at the PE documentation - however im still unsure how the concept will work.

The question for me still is :

The win32 program will load the data from itself - is the data internally declared as static - or do i even need to free memory - what has this to do with a PE declaration ?

If it is static, and using your initial size of 0xbeef for the data field - i would be able to manipulate the size after it has been compiled - correct ? then, i would be able to replace the data of my data field - however im still unsure where or how i can replace the data (given that i know that i can just manipulate the size of the data array).

Sorry if i explained it unclear.

0xf001
April 5th, 2006, 10:11
hehe,

you confuse me, too. i thought you yourself will create the C program under win.
Once compiled, you want to change the size of this data, right (w/o recompiling)?
And you want to do that on an UX system, right?

If yes - then prepare the C program so either it puts the data in an own and last section of the PE, that would make it easiest but without C and compiler knowledge a bit hard.

Once the PE (.exe) is compiled you cant simply add or remove or resize sthg, it needs to be reflected in the tables of the PE headers which are used to load your prog by the loader which is part of the OS.

That is why i suggested to study the PE header - the manipulation is probably not too difficult but must follow some rules.

All is highly dependent on how you access the data from within your C prog, and how you layout that file. are there requirements? what C program is that?

cheers, 0xf001

0xf001
April 5th, 2006, 11:09
ok,

i read your 1st post again. So this C program is your test, the other one you will not have the src to recompile I understand. In that case ... its maybe the best you lean back, and study
how a process under win gets executed, how the OS loads your program, what are sections and all that. You will need a proper understanding of how a PE file is structured,
good to know would be also how a C compiler works, esp with datestructures.

You will then better see why this section stuff etc is involved.

I am a bit curious why you use unix then when you code java - it could run on win, too.

so long,

0xf001

Harakiri
April 5th, 2006, 12:11
Quote:
[Originally Posted by 0xf001]ok,

i read your 1st post again. So this C program is your test, the other one you will not have the src to recompile I understand. In that case ... its maybe the best you lean back, and study
how a process under win gets executed, how the OS loads your program, what are sections and all that. You will need a proper understanding of how a PE file is structured,
good to know would be also how a C compiler works, esp with datestructures.

You will then better see why this section stuff etc is involved.


I figured it is not an easy task, but that it involves so much indeept knowledge of the system is frightening for a (for me as a programmer) theoretical easy task

Quote:
[Originally Posted by 0xf001]
I am a bit curious why you use unix then when you code java - it could run on win, too.
so long,
0xf001


no, its a server task that will run only on unix servers and its written in java - the users which use the server are actually (mostly) windoze users therefor i wanted to create an executeable under unix which can be openend under windows - i know this my sound strange but it has to be like that... java is just the server language currently for the task - i wouldnt even mind doing some exec calls on the unix but i dont think that would help me in anyway since it all boils down to byte manipulation of the native exec

dELTA
April 5th, 2006, 15:46
If you don't want to bother with PE manipulation (which after all is quite unnecessary in this case, despite everything said by all the show-offs in this thread ), simply append the data to the end of the exe-file, and then patch one single 32-bit integer constant inside the excutable to contain the length of this data.

During runtime, let the win32.exe read the X bytes from the end of its own executable (where X is taken from the patched constant) into a memory buffer (or even better, memory map this section of the file, but since this thread has had enough showing off already, let's not bother that ). And bam, you're done.

I could of course tell you about the method involving writing a kernel driver that uses the laser on your DVD drive to scan the contents of the screen through reflections in the eyes of the user, while flashing the contents of the data really fast on the screen with a DirectX shader model 3 program if you want, just let me know, but somehow I got the silly idea that you maybe wanted it done the easy way.

Harakiri
April 5th, 2006, 16:06
Quote:
[Originally Posted by dELTA]During runtime, let the win32.exe read the X bytes from the end of its own executable (where X is taken from the patched constant) into a memory buffer (or even better, memory map this section of the file, but since this thread has had enough showing off already, let's not bother that ). And bam, you're done.


thanks for the suggestion - so actually my reply about implementing :

Quote:
[Originally Posted by Harakiri]
do you mean i should just statically create a pointer which should always look inside the exe starting from offset 0xbeef ? right ?
And then again, in my java program i just append everything after 0xbeef with my data ?
[..] or can i just append random data to the end of the binary as long as i would like ?


wasnt that far off - right ?

Quote:
[Originally Posted by dELTA]
and then patch one single 32-bit integer constant inside the excutable to contain the length of this data.


so furthermore i dont even need to modify the patched constant for the data i figure right ? please check this pseudo code :

Code:

// after compile this file will be 1000 bits (guess)
static int myWin32OriginalFileSize = 1000;
main {
// open in read mode - win32proc.exe is THIS program currently
FILE *fp = fopen ("win32proc.exe", "rb";

// seek to the original exec end
fseek (fp, myWin32OriginalFileSize, SEEK_SET);


int len;
char buffer[1024];
// the data i appended at the end of the file will be written to mydata.bin
FILE *patchedData = fopen("mydata.bin","w";

// read everything from original end of exe till the new end of the exec
while((len = fread(buffer,1,sizeof(buffer),fp)) > 0)
{
// write to temp file mydata.bin for further processing
fwrite(buffer,1,len,patchedData);
}

// done i now have my data original data in a file called mydata.bin

}



Question: I still have the unanswered question - can i just append binary data to a win32 exec (no matter if 1bit or 10MB) and not break it ?


thanks

goggles99
April 5th, 2006, 16:34
OK, I tried to find info on a PE section size limit, and could not find any. It appears that I was incorrect about this. You should be able to add the section with no problems. You need to read documentation about the PE file structure if you want to go this route...

It would be easier to append the data to the end of the executable file, but not as elegant. You could just append the encrypted data right onto the end. either make start/end markers such as |dStart|...encrypted data...|dEnd| And have the C-executable parse the file for them, or make the last 4 bytes of the appended data the size of the appended data, and move backwards to offset (encrypted data size - total file size).


EDIT: looks like I just reiterated what delta posted above, I wrote the message and forgot to hit submit a few hours ago.

Oh well, I suggested appending the file days ago in the first place delta LOL You'r just better at splaining things i guess...

Quote:
Question: I still have the unanswered question - can i just append binary data to a win32 exec (no matter if 1bit or 10MB) and not break it ?

Yes you can append as much data to the end of the file as you want (Within file-system limitations) and it won't break it.

Harakiri
April 5th, 2006, 16:55
Hehe, finally i got it to work
Code:

#include <io.h>
#include <stdio.h>
#include <malloc.h>


static long execOriginalFileSize = 32768;
static char *execFileName = "Win32Wrapper.exe";

int main () {
FILE * pFile;
long execModifiedFileSize;
char * buffer;
long appendedDataSize;
size_t bytesRead;

pFile = fopen ( execFileName , "rb" );

if (pFile==NULL) {
printf("Could not open %s!\n",execFileName);
return -1;
}

// obtain file size.
fseek (pFile , 0 , SEEK_END);
execModifiedFileSize = ftell (pFile);
rewind (pFile);

// seek to original size
fseek (pFile, execOriginalFileSize, SEEK_SET);

appendedDataSize = (execModifiedFileSize - execOriginalFileSize);

printf("Original File Size : %i\n",execOriginalFileSize);
printf("Modified File Size : %i\n",execModifiedFileSize);
printf("Appended Data Size : %i\n",appendedDataSize);

// allocate memory to contain the whole appended data
buffer = (char*) malloc (appendedDataSize);

if (buffer == NULL) {
printf("Could not allocate any buffer for fread!";
return -1;
}

// copy the file into the buffer.
bytesRead = fread (buffer,1,appendedDataSize,pFile);

/*** the whole file is loaded in the buffer. ***/

printf("Read %i bytes, expected %i bytes!\n",bytesRead, appendedDataSize);

// santiy check here
if((long)bytesRead == appendedDataSize) {
;
} else {
printf("Result differs, exiting!";
return -1;
}

printf("Read Data : %s",buffer);

// terminate
fclose (pFile);
free (buffer);
return 0;
}



In java i just append data to that exec...done.

Is there any known siteeffects ? I just tried 1 MB Data or 10 bit data - worked flawless

0xf001
April 5th, 2006, 16:59
lol dELTA all the show-offs were probably just trying to help

I for myself admit I did not think about this easiest way as I had a bit problems understanding what he really wants. I assumed it shall work all inside his PE datastuctures where he clearly stated he has a buffer in his C prog "Hello world" which he wants to resize (and which would be far more interesting ).
With the 0xbeef I wanted to help him find the offset of his length variabl to patch and blah ...

With the whole picture in mind .... you're just right

cheers,

0xf001

Harakiri
April 5th, 2006, 18:40
Hey guys, if the adding of additional data to an exec is perfectly valid could you explain this entry ?

http://www.heaventools.com/PE_Explorer_file_repair.htm

Every version of Windows NT (including 2000 and XP) adds the HeaderSize to the sum of the SizeOfRawData values from each section and checks the result against the SizeOfImage value obtained from the PE file's optional header. If the calculated value is greater than the reported SizeOfImage value, the discrepancy is registered as a fatal error, the continued loading of the damaged file is blocked, and the user receives a "This file is not a valid Win32 application" message. Otherwise, loading continues and control is passed to the particular file.

i used the LordPE Tool the files (orginal, modified) seem to be OK except SizeOfImage differs...

goggles99
April 5th, 2006, 20:19
Quote:
sum of the SizeOfRawData values from each section

The data that you are adding is not inside of any defined section.
I wouldn't have suggested this idea if it would cause a problem...

BTW, malloc is not generally used directly in C++, you should use the "new" directive instead. In theory, "new" allocates objects from the "free store". malloc allocates memory from the heap. I've seen a heap overflow once though when a large amount of data was allocated with malloc.



EDIT: I just thought of something else. Using the "Append" method has another advantage. Since the data is not in any defined PE section, and therefore not loaded into memory (Much less even read by the windows loader) initial execution up to idle state of the application should be fairly quicker than if you had added a 20meg data section.

Silver
April 6th, 2006, 04:59
Damn, you solved it already, and I was up all night coding a pixel shader that would do this on the GPU of a Radeon....

Damn delphi coders :P

Glad you got it working, anyway.

Maximus
April 6th, 2006, 07:39
if anyone like delphi, google for exemod.zip

It shows the job (late, sorry, I knew I had it something like it somewhere around my HD ...but I can't trust google toolbar :confused

Harakiri
April 6th, 2006, 08:05
Quote:
[Originally Posted by Silver]Damn, you solved it already, and I was up all night coding a pixel shader that would do this on the GPU of a Radeon....

Damn delphi coders :P

Glad you got it working, anyway.


thanks but what delphi code ?

this is pure C ANSI

dELTA
April 6th, 2006, 10:53
Quote:
thanks but what delphi code ?
I think he might just have been referring to my personal coding preferences (which he knew from elsewhere), in just the same way I was referring to his in my post...

Maximus
April 6th, 2006, 11:56
Just in case, edit Windows header and add&recompile
Code:

ExtendedRegisters: array [0..511] of Byte;

to the CONTEXT declaration, or remember to add a 512 byte buffer after its allocation or, better, allocate the whole object it dynamically and typecast the pointer to a PContext.