473,597 Members | 2,459 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Injecting Code to an existing PE

Hi,

Introduction:
*************** *************** *************** ***************
I am working on a project that should encrypt PE files ( Portable executable
), this require me to inject some code to existing PEs.
First, I have tried:
1. to inject some code to the end of the ‘.text’ segment of an existing PE
2. to set the entry point RVA to the address of the injected code
3. at the end of the injected code I have set a jmp to the original entrypoint
The problem:
Opening that file and browsing to the entrypoint address I can see the
injected code BUT when running the application I can see that the IP points
to the correct address ( Base + RVA ) but the injected code is not there (
just some gibberish ), I tried setting the following flags for the section:
‘IMAGE_SCN_ME M_PRELOAD | IMAGE_SCN_CNT_C ODE |
IMAGE_SCN_CNT_I NITIALIZED_DATA ’, BUT still, No good, I get the same results…
A .Any comments remarks or pointers will be appreciated.
B. Any pointers to documentation concerning how the PE loader work will be
appreciated ( e.g. which sections are loaded when, … )

*************** *************** *************** ***************
Following is the code I use:
HRESULT InjectCode(char *pSourceName, char *pTargetName)
{
DWORD dwBytesRead = 0;
BYTE *pFileMemImage = 0;
LARGE_INTEGER liSourceSize;
HANDLE hSource = CreateFile(pSou rceName, GENERIC_READ,
FILE_SHARE_READ ,
0,
OPEN_EXISTING,
FILE_ATTRIBUTE_ NORMAL,
0);
if(0 == hSource)
return HRESULT_FROM_WI N32(GetLastErro r());
GetFileSizeEx(h Source, &liSourceSiz e);
pFileMemImage = new BYTE[(DWORD)liSource Size.QuadPart];
ReadFile(hSourc e, pFileMemImage,
(DWORD)liSource Size.QuadPart,
&dwBytesRead , 0);
CloseHandle(hSo urce);

IMAGE_DOS_HEADE R *pdosHeader = (IMAGE_DOS_HEAD ER*)pFileMemIma ge;
IMAGE_NT_HEADER S32 *pNtHdr = (IMAGE_NT_HEADE RS32*)(pFileMem Image +
pdosHeader->e_lfanew);
IMAGE_SECTION_H EADER *pSecHeader = (IMAGE_SECTION_ HEADER*)((PBYTE )pNtHdr +
sizeof(*pNtHdr) );

DWORD dwWrittenBytes = 0;
// Copy the new function to the end of the '.text' segment
BYTE *pInjectedCode = pFileMemImage + pSecHeader[1].PointerToRawDa ta +
pSecHeader[1].Misc.VirtualSi ze -
sizeof(INJECTED _SEGMENT_LIBLOA D);
DWORD *pJumpAddress = (DWORD*)(pInjec tedCode +
sizeof(INJECTED _SEGMENT_LIBLOA D) -
sizeof(DWORD));
memcpy(pInjecte dCode, INJECTED_SEGMEN T_LIBLOAD,
sizeof(INJECTED _SEGMENT_LIBLOA D));
pSecHeader[1].Characteristic s |= IMAGE_SCN_MEM_P RELOAD | IMAGE_SCN_CNT_C ODE
| IMAGE_SCN_CNT_I NITIALIZED_DATA |
IMAGE_SCN_LNK_R EMOVE;

*pJumpAddress = pNtHdr->OptionalHeader .AddressOfEntry Point -
(DWORD)((PBYTE) pJumpAddress - 1);

pNtHdr->OptionalHeader .AddressOfEntry Point = (DWORD)(pInject edCode -
pFileMemImage);

HANDLE hTarget = CreateFile(pTar getName, GENERIC_WRITE, 0, 0,
CREATE_ALWAYS, FILE_ATTRIBUTE_ NORMAL, 0);
WriteFile(hTarg et, pFileMemImage, (DWORD)liSource Size.QuadPart,
&dwWrittenBytes , 0);
CloseHandle(hTa rget);

return S_OK;
}

--
Nadav
http://www.ddevel.com
--
Nadav
http://www.ddevel.com
Nov 17 '05 #1
5 2876
Nadav wrote:
I am working on a project that should encrypt PE files ( Portable executable
), this require me to inject some code to existing PEs.


I believe this is caused by not updating the size of the .text section,
therefore the loader doesn't map your injected code into memory.
http://msdn.microsoft.com/msdnmag/is...E/default.aspx

"It's important to note that PE files are not just mapped into memory as
a single memory-mapped file. Instead, the Windows loader looks at the PE
file and decides what portions of the file to map in."

This sems to make sense also because then the section header's
characteristics (IMAGE_SCN_MEM_ READ etc) can easily be applied to the
different memory pages.

--
Ben
http://bschwehn.de
Nov 17 '05 #2
Hi Ben,

Thanks again for your responce, The code I add to the '.text' segment is
added at the end on the existing '.text' segment (the existing segment is not
enlarged) e.g. if the size of the '.text' segment is X i add the code at
[Base + X - 'Size of injected code'] this may override existing data in case
the actual data size is alligned to 0x1000, BUT on first stage I would like
to avoid enlaging the '.text' segment size, after achieving what was just
described I would try to enlarge the .text segment ( changing existing RVAs
and so )..., anyhow, back to the problem, putting the code at the position
just mentioned works fine as long as for the written file, BUT when the
loader load the file it seems the requiered segment is not mapped... I
wonder... why does not all of the '.text' segment is mapped to memory? how
should I configure the PE so it will load all of the '.text' segment... what
flags should I set in addition to the one I have alerady set (see my root
query)?

"Ben Schwehn" wrote:
Nadav wrote:
I am working on a project that should encrypt PE files ( Portable executable
), this require me to inject some code to existing PEs.


I believe this is caused by not updating the size of the .text section,
therefore the loader doesn't map your injected code into memory.
http://msdn.microsoft.com/msdnmag/is...E/default.aspx

"It's important to note that PE files are not just mapped into memory as
a single memory-mapped file. Instead, the Windows loader looks at the PE
file and decides what portions of the file to map in."

This sems to make sense also because then the section header's
characteristics (IMAGE_SCN_MEM_ READ etc) can easily be applied to the
different memory pages.

--
Ben
http://bschwehn.de

Nov 17 '05 #3
You're right of course.

If tried your code with some minor adjustments and the injected code is
there when the PE is executed.
Perhaps you're just looking at the wrong location? ;)

The most significant change i made is

pNtHdr->OptionalHeader .AddressOfEntry Point =
pSecHeader[0].VirtualAddress - pSecHeader[0].PointerToRawDa ta +
(DWORD)(pInject edCode - pFileMemImage);

since you have to translate the EntryPoint to a RVA. (pSecHeader[0] ist
the text section header of my test file). Often
pSecHeader[0].VirtualAddress - pSecHeader[0].PointerToRawDa ta is 0 so it
doesn't matter. Don't know if this is causing you're problem...?

Only tested it with injecting 0xc3 (ret) and 0xcc (breakpoint) but that
worked.

ben

Nov 17 '05 #4
Hi Ben,

Thanks for your response, Indeed setting the entry point as you have advised
solved the problem, Now I have tried to extend the '.text' segment so
existing data would not be overwritten, to achieve that I have used the
ICeeFileGen interface provided by Microsoft (the app i am injecting
[unmanaged] code to is a managed executable, starting with an unmanaged JMP
_CorExeMain), I have successfully extended the segment and injected my code,
BUT, when setting the entrypoint of the executable to a location other then
it's original position I get 0xC000007B => STATUS_INVALID_ IMAGE_FORMAT,
injecting the code without changing the entrypoint causes the PE to execute
normally, using some common PE disassembler ( PE Explorer ) I can see the
modified entrypoint points to the right RVA:
( The injected code is added right after the original code )
jmp_mscoree.dll !_CorExeMain://<==The original entrypoint
jmp [mscoree.dll!_Co rExeMain]
;----------------------------------------------------------------------
EntryPoint:// <== the updated entrypoint
push ebp
mov ebp,esp
sub esp,000000FCh
push ebx
push esi
blablabla...

My guess is that additional configuration is needed to be done to the PE
headers so 0xC000007B will not show... what it is... i don't really
know.......

The Injection/entrypoint modification code:
HRESULT AssemblyEmitter ::PEWriter::Inj ectCode()
{
HCEESECTION Section = 0;
HRESULT hr = FileGen->GetSectionCrea te(ceeFile,
".text",
0,
&Section);
if(FAILED(hr))
return hr;
char *pCode = 0;
hr = FileGen->GetSectionBloc k(Section,
sizeof(INJECTED _SEGMENT_LIBLOA D),
4,
(void**)&pCode) ;
if(FAILED(hr))
return hr;
memcpy(pCode, INJECTED_SEGMEN T_LIBLOAD,
sizeof(INJECTED _SEGMENT_LIBLOA D));
return FileGen->ComputeSection Offset(Section,
pCode,

&m_pEmitter->m_uiInjectedCo deEntryPoint);
}

HRESULT AssemblyEmitter ::PEWriter::Upd ateEntryPoint(W CHAR *pSourceName)
{
DWORD dwBytesRead = 0;
BYTE *pFileMemImage = 0;
LARGE_INTEGER liSourceSize;
HANDLE hSource = CreateFile(pSou rceName,
GENERIC_READ,
FILE_SHARE_READ ,
0,
OPEN_EXISTING,
FILE_ATTRIBUTE_ NORMAL,
0);
if(0 == hSource)
return HRESULT_FROM_WI N32(GetLastErro r());
GetFileSizeEx(h Source, &liSourceSiz e);
pFileMemImage = new BYTE[(DWORD)liSource Size.QuadPart];
ReadFile(hSourc e, pFileMemImage,
(DWORD)liSource Size.QuadPart,
&dwBytesRead , 0);
CloseHandle(hSo urce);

IMAGE_DOS_HEADE R *pdosHeader = (IMAGE_DOS_HEAD ER*)pFileMemIma ge;
IMAGE_NT_HEADER S32 *pNtHdr = (IMAGE_NT_HEADE RS32*)(pFileMem Image
+ pdosHeader->e_lfanew);
IMAGE_SECTION_H EADER *pSecHeader = (IMAGE_SECTION_ HEADER*)((PBYTE )pNtHdr
+ sizeof(*pNtHdr) );
DWORD dwWrittenBytes = 0;
IMAGE_SECTION_H EADER *pSec = 0;
for(int i = 0; i < pNtHdr->FileHeader.Num berOfSections; i++)
{
pSec = pSecHeader + i;
if(0 == strcmp(".text", (char*)pSec->Name))
break;
pSec = 0;
}
if(0 == pSec)
return E_FAIL;
// Copy the new function to the end of the '.text' segment
IMAGE_DATA_DIRE CTORY *pdd =
(IMAGE_DATA_DIR ECTORY*)pNtHdr->OptionalHeader .DataDirectory
+ IMAGE_DIRECTORY _ENTRY_COMHEADE R;
DWORD dwCorhdrOffset = pdd->VirtualAddre ss
+ pdd->Size
- pSec->VirtualAddress ;
BYTE *pInjectedCode = pFileMemImage
+ pSec->PointerToRawDa ta
+ m_pEmitter->m_uiInjectedCo deEntryPoint
+ dwCorhdrOffset;
DWORD *pJumpAddress = (DWORD*)(pInjec tedCode
+ sizeof(INJECTED _SEGMENT_LIBLOA D)
- sizeof(DWORD));
// pSec->Characteristic s |= 0xc0000040;
DWORD dwOriginalAddre ss = pNtHdr->OptionalHeader .AddressOfEntry Point;
pNtHdr->OptionalHeader .AddressOfEntry Point =
pSec->VirtualAddre ss
+ m_pEmitter->m_uiInjectedCo deEntryPoint
+ dwCorhdrOffset;
*pJumpAddress = dwOriginalAddre ss
- (pNtHdr->OptionalHeader .AddressOfEntry Point
+ sizeof(INJECTED _SEGMENT_LIBLOA D));
DeleteFile(pSou rceName);

HANDLE hTarget = CreateFile(pSou rceName,
GENERIC_WRITE,
0,
0,
CREATE_ALWAYS,
FILE_ATTRIBUTE_ NORMAL,
0);
WriteFile(hTarg et,
pFileMemImage,
(DWORD)liSource Size.QuadPart,
&dwWrittenBytes ,
0);
CloseHandle(hTa rget);

return S_OK;
}

"Ben Schwehn" wrote:
You're right of course.

If tried your code with some minor adjustments and the injected code is
there when the PE is executed.
Perhaps you're just looking at the wrong location? ;)


Nov 17 '05 #5
There are a lot of information about PE file structures, loader and so
on, try, for example, http://win32asm.cjb.net/ or if you understand
Russian (http://www.wasm.ru)

If I should implement the similar project, I simplify my task to avoid
Windows PE loader:

1. run PE file as secondary process using CreateProcess with
CREATE_SUSPENDE D
flag (may be OR with DEBUG_PROCESS flag too)

2. modify code of already loaded PE file, using WriteProcessMem ory

Some other functions should be used as well: OpenProcess and
VirtualProtectE x

Regards:
http://ircdb.org
http://smike.ru
http://xedit.smike.ru
Nov 17 '05 #6

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

17
6501
by: George Sakkis | last post by:
Is there a general way of injecting code into a function, typically before and/or after the existing code ? I know that for most purposes, an OO solution, such as the template pattern, is a cleaner way to get the same effect, but it's not always applicable (e.g. if you have no control over the design and you are given a function to start with). In particular, I want to get access to the function's locals() just before it exits, i.e....
10
6835
by: Brian W | last post by:
Hi All, I have a web user control that, among other things, provides Print this page, and Email this page functionality I have this script that is to execute on the click of the asp:hyperlinks I have a function in a <SCRIPT> block that I want in the <head></head> section of the page. Unfortunately, RegisterClientScriptBlock, RegisterStartupScript don't always work, and when they do the script is placed inside the <form> tag (this...
2
2349
by: Christopher Ambler | last post by:
I'm wondering if there's a solution here - I have an ASPX page with a sole purpose of scaling an image. The ASPX page contains a single line with the codebehind tag, and the .cs file contains the code to read an image, use GDI+ to scale it to a reasonable size, and emit the image directly (setting content-type on the response and spitting out the bytes for the image). What I'd love to do would be to eliminate the ASPX page and be able...
17
1562
by: Luke Matuszewski | last post by:
Hi ! Simple question (but thus it may appear no simple answer): If i putting a script onto the page i simply could inline it in <script> element or via its src attribute so (second way): <script type="text/javascript" src="js/crossBrowserDegradationLib.js"> </script> , my question is simple What encoding should i use when writting my crossBrowserDegradationLib.js: a) should it be the same encoding like encoding of my web page (and the
9
3514
by: tai | last post by:
Hi. I'm looking for a way to define a function that's only effective inside specified function. Featurewise, here's what I want to do: bar_plugin_func = function() { ...; setTimeout(...); ... }; wrap_func(bar_plugin_func); bar_plugin_func(); // calls custom "setTimeout"
14
1771
by: ofiras | last post by:
Hii everyone, I'm a web programmer, but I never understood sql injecting. All I found was that you can write "a' or 'a'='a" in the password field to try to connect without knowing the password. I heard that there are many other ways to do sql injecting, and I never found how. I know that you can even manage to get data from sql tables using sql injecting. How can it be? How can someone do it? Please help,
4
1140
by: Peter Waller | last post by:
Dear Pythoners, I know this will probably be perceived as 'evil voodoo', and fair enough: it probably is. I guess it is unpythonic. ... but I want to know how to do it anyway - mostly for my own interest. Consider the following snippet of code:
1
1866
by: rh.krish | last post by:
Hi, I have a unique situation. We have many applications (approx - 20) built on .NET framework 1.1 & 2.0 and hosted in one single IIS website in PROD. We have similar setup in TEST. Now we want to have a banner indicating that the website being accessed by the user is TEST. This is because, there are some users who have access to both and sometimes they do stuffs in PROD which are meant to be done only in TEST. By displaying somekind of...
0
7971
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
7893
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
8276
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
8381
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
0
8259
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
6698
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
5847
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
3889
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
1
1495
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.