Jump to content
Tuts 4 You
Sign in to follow this  
kincses

Read/Write ProcessMemory of Private block

Recommended Posts

kincses

Hi.

Making a new thread for this, but is actually a sub-problem coming from my other thread.

 

I'm trying to make a loader (now in c++), which would use the ReadProcessMemory API.

The process is created by the loader with

CreateProcess(address,NULL,NULL,NULL,FALSE,CREATE_SUSPENDED,NULL,NULL,&startup_info,&process_info)

I noticed, that while it reads the memory of an "Imag" memory block, it returns 0x00 (or 0xCC ?) when trying to read from a private memory area.

How is this bypassable?

Share this post


Link to post
crystalboy

As always MSDN is your friend. :)

You can use VirtualProtect to change permission of page/sections.

Share this post


Link to post
kincses

Silly me, I was using that (VirtualProtectEx to be exact but they seem to do the same essentially), just did not check for the error which it gave.

 

Seemingly fixed those. Changed:

Quote

void* address = (void*)0x0019FF28;

to

Quote

unsigned int address = 0x0019FF28;

Still returns garbage. Next idea? I'm assuming a lack of permissions would return an error too, so that should not be it.

Edited by kincses (see edit history)

Share this post


Link to post
crystalboy

You are calling VirtualProtect using RVA, that's why your call fail.

Before successfully call it you need to get the base address of loaded PE and sum RVA ( 0x0019FF28 )

  • Like 1

Share this post


Link to post
deepzero

Prefer void* over uint for pointers.

 

As for your problem as he said, msdn is your friend.

 

Quote

Changes the protection on a region of committed pages in the virtual address space of the calling process.

That's your loader process. If you want to read the memory of another process (the one you just created) you need another API function. Which one might that be?

 

Quote

To change the access protection of any process, use the VirtualProtectEx function.

;)

VirtualProtectEx needs another paramter: a Handle to the process. Where can you get that? From the processinformation structure: process_info.hProcess.

 

  • Like 1

Share this post


Link to post
kao
3 hours ago, kincses said:

it returns 0x00 (or 0xCC ?)

Sounds like uninitialized data. Are you checking the return value of ReadProcessMemory?

3 hours ago, kincses said:

CREATE_SUSPENDED

You do realize that suspended process doesn't run, the packer layer is not executed and therefore unpacked exe code is not present in memory, etc.? With the same success you could just use ReadFile and read from EXE file directly.

Or, you're calling CreateThread/ResumeThread at some point and just didn't tell us?

  • Like 1

Share this post


Link to post
kincses
53 minutes ago, crystalboy said:

You are calling VirtualProtect using RVA, that's why your call fail.

Before successfully call it you need to get the base address of loaded PE and sum RVA ( 0x0019FF28 )

I'm actually using VirtualProtectEx(did I edit it too slow?), and even without it, ReadProcessMemory reads non-private memory correctly, so am I really not on the right track? Do private memory act different than non-private?

51 minutes ago, deepzero said:

Prefer void* over uint for pointers.

Was using that, did not work any way, it just generated an "Attempt to access invalid address" error (related to crystalboy's reply maybe?)

Quote

VirtualProtectEx needs another paramter: a Handle to the process. Where can you get that? From the processinformation structure: process_info.hProcess.

Which I do pass to it, obtained from the CreateProcess, that should be OK, shouldn't it be?

Share this post


Link to post
kincses
1 minute ago, kao said:

Sounds like uninitialized data. Are you checking the return value of ReadProcessMemory?

You do realize that suspended process doesn't run, the packer layer is not executed and therefore unpacked exe code is not present in memory, etc.? With the same success you could just use ReadFile and read from EXE file directly.

Or, you're calling CreateThread/ResumeThread at some point and just didn't tell us?

That's what I thought too, thing is, it even fails to read data that is present in ollydbg at load, (without executing the software), other than that, it would add up.

Yes, I believe I am resuming it, might be wrong though because it does not seem to have the correct values at the planned breakpoint. (I am trying to read memory at a certain address execution).

 

Good points, might be where I screwed it up. Have to look into it too...

Share this post


Link to post
evlncrn8

do a small test then, read the base address of the target process.. to see if the good old MZ is there, if that works, then expand on the code.. i dont think the api's are at fault here..

Share this post


Link to post
kincses
3 hours ago, kao said:

You do realize that suspended process doesn't run, the packer layer is not executed and therefore unpacked exe code is not present in memory, etc.?

Seems like you were right and it stayed in suspended mode, instead of stopping at the HWbreakpoint.

And I have no further idea how to bypass this, sounds so simple and yet...

I don't suppose anyone would be interested in making this for me in exchange of a small reward.

Edited by kincses (see edit history)

Share this post


Link to post
kao
14 minutes ago, kincses said:

anyone would be interested in making this for me in exchange of a small reward

Arghh.. And you started so well, trying to learn and asking smart questions. :(

If you're going to ask someone else to do your job, why not ask for a properly unpacked file instead?

  • Like 4

Share this post


Link to post
deepzero

@kincses
 Come on mate. You can do it. Not that hard. :)

To me more and more questions arise ... for example, where does that hwbp in your target process come from?

1. post your full code
2. describe what you expect to happen and what actually happens.

  • Like 2

Share this post


Link to post
kincses
14 hours ago, kao said:

Arghh.. And you started so well, trying to learn and asking smart questions. :(

If you're going to ask someone else to do your job, why not ask for a properly unpacked file instead?

Because I want to see where I f*cked it up, can't do that from an unpacked file, right?

14 hours ago, deepzero said:

Come on mate. You can do it. Not that hard. :)

That's what I thought, but I'm on this for almost a week without any progress.

I am finding threads about the same thing I wish to accomplish from 2003 and even those are without response or with dead links.

Share this post


Link to post
mrexodia

We cannot magically guess what your code is doing from very vague descriptions, please post the full code. What are you trying to accomplish with the suspended process?

Share this post


Link to post
kincses
22 minutes ago, mrexodia said:

We cannot magically guess what your code is doing from very vague descriptions, please post the full code. What are you trying to accomplish with the suspended process?

Its a work-in-progress pile of mess, that's why I did not intend on posting it, but alright...

Quote

#include "stdafx.h"
#include <Windows.h>
#include <stdio.h>
#include "HwBrk.h"
#include <iomanip>
#include <thread>

class HWBRK 
{ 
public: 
	void* a; 
	HANDLE hT; 
	HWBRK_TYPE Type; 
	HWBRK_SIZE Size; 
	HANDLE hEv; 
	int iReg; 
	int Opr; 
	bool SUCC; 

	HWBRK() 
	{ 
		Opr = 0; 
		a = 0; 
		hT = 0; 
		hEv = 0; 
		iReg = 0; 
		SUCC = false; 
	} 
}; 

void InjectDLL(HANDLE Proc);
void ModifyValues(HANDLE Proc);
HANDLE hwbrkEvent, hwbrkEvent2;
int FlagBit;
bool Dr0Busy ;
bool Dr1Busy ;
bool Dr2Busy ;
bool Dr3Busy ;

void SetBits(DWORD_PTR &dw, size_t lowBit, size_t bits, size_t newValue)
{
    DWORD_PTR mask = (1 << bits) - 1; 
    dw = (dw & ~(mask << lowBit)) | (newValue << lowBit);
}

static DWORD WINAPI th ( LPVOID lpParameter ) 
{
	//lpParameter is passed via the CreateThread parameter so it has
	//to be typecasted back to a HWBRK type
	HWBRK* h=(HWBRK*)lpParameter;
	int j=0; 
	int y=0;
	//Suspend the target thread so the breakpoint can be set. As a
	//reminder SuspendThread returns a threads SuspendCount
	j = SuspendThread (h->hT); 
	y = GetLastError();
	CONTEXT ct = {0};
	//Get the context of the DRX register set.
	ct.ContextFlags = CONTEXT_DEBUG_REGISTERS ;
	//If GetThreadContext succeeeds it returns a non- zero number
	//otherwise it returns 0
	j = GetThreadContext(h->hT,&ct);
	y = GetLastError();
	int FlagBit=0;
	//Set all debug registers as unused
	bool Dr0Busy = false;
	bool Dr1Busy = false;
	bool Dr2Busy = false;
	bool Dr3Busy = false;
	//Each of these correspond to the Global
	//breakpoint enable registers.
	if ( ct.Dr7 & 1 )
	{Dr0Busy = true;}

	if ( ct.Dr7 & 4 ) 
	{Dr1Busy = true;}

	if ( ct.Dr7 & 16 )
	{Dr2Busy = true ;}

	if( ct.Dr7 & 64 )
	{Dr3Busy = true ;}
	//Opr set to 1 means remove breakpoints
	if ( h -> Opr == 1 )
	{
		// Clear debug registers
		if ( h -> iReg == 0 ) 
		{ 
			FlagBit = 0 ; 
			ct.Dr0 = 0 ;
			Dr0Busy = false ;
		}
		if ( h -> iReg == 1 )
		{ FlagBit = 2 ;
		ct.Dr1 = 0 ;
		Dr1Busy = false ;
		}
		if ( h -> iReg == 2 )
		{
			FlagBit = 4 ;
			ct.Dr2 = 0 ;
			Dr2Busy = false ;
		}
		if ( h -> iReg == 3 )
		{
			FlagBit = 6 ;
			ct.Dr3 = 0 ;
			Dr3Busy = false ;
		}
		ct.Dr7 &= ~( 1 << FlagBit );
	}
	//If opr was 0 then the below sets the first available
	//debug register and marks it as used
	else
	{
		if(!Dr0Busy )
		{ 
			h -> iReg = 0 ;
			ct.Dr0 = (DWORD_PTR)h -> a ;
			Dr0Busy = true ;
		}
		else if(!Dr1Busy )
		{ h -> iReg = 1 ;
		ct.Dr1 = (DWORD_PTR)h -> a ;
		Dr1Busy = true ;
		}
		else if (!Dr2Busy)
		{ h -> iReg = 2 ;
		ct.Dr2 = (DWORD_PTR) h -> a ;
		Dr2Busy = true ;
		}
		else if (! Dr3Busy )
		{ h -> iReg = 3 ;
		ct.Dr3 =( DWORD_PTR)h -> a ;
		Dr3Busy = true ;
		}
		else { h -> SUCC = false ;
		j = ResumeThread ( h -> hT );
		y = GetLastError ();
		SetEvent ( h -> hEv );
		return 0;
		}

		ct.Dr6 = 0 ;
		int st = 0 ;

		if ( h -> Type == HWBRK_TYPE_EXECUTE )
			st = 0 ;

		if ( h -> Type == HWBRK_TYPE_READWRITE )
			st = 3 ;

		if ( h -> Type == HWBRK_TYPE_WRITE)
			st = 1 ;

		int le = 0 ;

		if ( h -> Size == HWBRK_SIZE_1 )
			le = 0 ;

		if ( h -> Size == HWBRK_SIZE_2 )
			le = 1 ;

		if ( h -> Size == HWBRK_SIZE_4 )
			le = 3 ;

		if ( h -> Size == HWBRK_SIZE_8 )
			le = 2 ;

		SetBits ( ct.Dr7 , 16 + h -> iReg * 4 , 2 , st );
		SetBits ( ct.Dr7 , 18 + h -> iReg * 4 , 2 , le );
		SetBits ( ct.Dr7 , h -> iReg * 2 , 1 , 1 );
	}
	ct.ContextFlags = CONTEXT_DEBUG_REGISTERS ;
	j = SetThreadContext ( h -> hT ,& ct );
	y = GetLastError ();
	ct.ContextFlags = CONTEXT_DEBUG_REGISTERS ;
	j = GetThreadContext ( h -> hT ,& ct );
	y = GetLastError ();
	j = ResumeThread ( h -> hT );
	y = GetLastError ();
	h -> SUCC = true ;
	SetEvent ( h -> hEv );
	return 0;
}

HANDLE SetHardwareBreakpoint(HANDLE hThread,HWBRK_TYPE Type,HWBRK_SIZE Size,void* s)
{
	//Set constants
	HWBRK* h=new HWBRK;
	//Create a new hardware breakpoint
	h->a=s;
	//Address of the breakpoint
	h->Size=Size;
	//Size of the breakpoint to be set
	h->Type=Type;
	//Type of breakpoint to set (read/write/execute)
	h->hT=hThread;
	//The thread to set the breakpoint in
	h->hEv=CreateEvent(0,0,0,0);
	h->Opr=0;
	// 0 specifies set breakpoint 1 specifies remove breakpoint
	//Create a remote thread to set the hardware breakpoints. Hardware breakpoints
	//are not global in windows. They are specific to the context of one thread.
	HANDLE hY = CreateThread(0,0,th,(LPVOID)h,0,0);
	//Wait for the breakpoint instance's event object to be placed in a signaled state.
	WaitForSingleObject(h->hEv,INFINITE);
	CloseHandle(h->hEv);
	h->hEv=0;
	if(hThread==GetCurrentThread())
	{
		CloseHandle(h->hT);
	}
	h->hT=hThread;
	if(!h->SUCC)
	{
		delete h;
		return 0;
	}
	return(HANDLE)h;
}

bool RemoveHardwareBreakpoint(HANDLE hBrk)
{
HWBRK* h = (HWBRK*)hBrk;
if (!h)
    return false;

bool C = false;
if (h->hT == GetCurrentThread())
    {
    DWORD pid = GetCurrentThreadId();
    h->hT = OpenThread(THREAD_ALL_ACCESS,0,pid);
   C = true;
    }

 h->hEv = CreateEvent(0,0,0,0);
 h->Opr = 1; // Remove Break
HANDLE hY = CreateThread(0,0,th,(LPVOID)h,0,0);
WaitForSingleObject(h->hEv,INFINITE);
CloseHandle(h->hEv);
h->hEv = 0;

if (C)
   {
    CloseHandle(h->hT);
   }

delete h;
return true;
}

bool RemoveHardwareBreakpoint_original(HANDLE hBrk)
{
	HWBRK* h=(HWBRK*)hBrk;
	if(!h)
		return false;

	bool C=false;
	//Suspend the target thread so the breakpoint can be set. As a
	//reminder SuspendThread returns a threads SuspendCount
	SuspendThread(h->hT);
	CONTEXT ct={0};
	//Get the context of the control register set.
	ct.ContextFlags=CONTEXT_CONTROL;
	//ct.ContextFlags = CONTEXT_DEBUG_REGISTERS;
	//Get the context of the thread.
	GetThreadContext(h->hT,&ct);
	//Set EIP to our target address
	//ct.Eip=0x004010D4;
	SetThreadContext(h->hT,&ct);
	ResumeThread(h->hT);
	delete h;
	return true;
}

BOOL main(int argc,char* argv[])
{
	PROCESS_INFORMATION process_info;
	STARTUPINFO startup_info;
	//0 out the area for our process' structures
	ZeroMemory(&startup_info,sizeof(startup_info));
	startup_info.cb =sizeof(startup_info);
	ZeroMemory(&process_info,sizeof(process_info));
	//Grabthe process to be loaded. (In this case that should be
	//the duelist 5 executable file due-cm5.exe
	if(!::CreateProcess("C:\\Program Files (x86)\\KRESZTESZT\\KRESZTESZT1501B.exe",//LPCTSTR lpApplicationName
		//Specify path/name on command line
		NULL,
		//LPTSTR lpCommandLine
		//Returns a pointer to the command line
		NULL,
		//LPSECURITY_ATTRIBUTES lpProcessAttributes
		//Process handle not inheritable
		NULL,
		//LPSECURITY_ATTRIBUTES lpThreadAttributes
		//Thread handle not inheritable
		FALSE,
		//BOOL bInheritHandles
		//Set handle inheritance to FALSE
		CREATE_SUSPENDED,
		//DWORD dwCreationFlags
		//Use suspended creation flags
		NULL,
		//LPVOID lpEnvironment
		//Use parent's environment block
		NULL,
		//LPCTSTR lpCurrentDirectory
		//Use parent's starting directory
		&startup_info,
		//LPSTARTUPINFO lpStartupInfo
		//Pointer to STARTUPINFO structure
		&process_info)
		//LPPROCESS_INFORMATION lpProcessInformation
		//Pointer to PROCESS_INFORMATION struture.
		){
			//If the process can't be created return an error message.
			printf("CreateProcess failed (%d).\n",GetLastError());
			return FALSE;
	}
	
	//The address to place the breakpoint at.
	void* ptr =(void*)0x00DF5435;
	printf("Setting hardware breakpoint...\n");
	//Set the hardware breakpoint.
HANDLE hardwareBreakpoint =SetHardwareBreakpoint(process_info.hThread,HWBRK_TYPE_EXECUTE,HWBRK_SIZE_1,ptr);

//a.join();
	//Create an event that will be signaled when we are ready to remove the hardware
	//breakpoint.

hwbrkEvent =CreateEvent(NULL,TRUE,FALSE,"hwbrkEvent");
hwbrkEvent2 =CreateEvent(NULL,TRUE,FALSE,"hwbrkEvent2");
	//Make sure the event was created.
	if(hwbrkEvent ==NULL)
	{
		printf("CreateEvent error: %d\n",GetLastError());
		return FALSE;
	}
ResumeThread(hardwareBreakpoint);
	printf("Starting modification process...\n");
	//ModifyValues(process_info.hProcess);
	printf("Resuming thread...\n");
	//Resume the thread
//ResumeThread(process_info.hThread);
	printf("Waiting to remove breakpoint...\n");
	//Wait for the event object to be signaled.
//std::thread first (ModifyValues,process_info.hProcess);
	//first.join();
//ResumeThread(process_info.hThread);
//SetEvent(hwbrkEvent);
	//ResumeThread(process_info.hThread);
//WaitForSingleObject(hwbrkEvent2,INFINITE);
	
	//ModifyValues(process_info.hThread);
	//Remove the hardware breakpoint
	printf("Waiting to remove breakpoint...2\n");
	RemoveHardwareBreakpoint(hardwareBreakpoint);
	printf("Waiting to remove breakpoint...3\n");
	//Tell the injected dll that the hardware breakpoint has been removed
//hwbrkEvent2 =OpenEvent(EVENT_MODIFY_STATE,FALSE,"hwbrkEvent2");
	//Make sure the event successfully opened
	/*if(hwbrkEvent2 ==NULL)
	{
		printf("Event failed to open.");
		return FALSE;
	}
	SetEvent(hwbrkEvent2);*/
	//Set the event back to unsignaled
	//ResetEvent(hwbrkEvent);
	printf("Closing handle to process...\n");
	//Close the handle and return.
//ResumeThread(process_info.hThread);
//WaitForSingleObject(process_info.hProcess, INFINITE);
    CloseHandle(process_info.hProcess);
    CloseHandle(process_info.hThread);
	//CloseHandle(process_info.hProcess);
	return TRUE;
}
/*void InjectDLL(HANDLE Proc)
{
	//Declare constants.
	char buf[50]={0};
	LPVOID RemoteString,LoadLibAddy,SetHandler;
	LPCSTR DLL_NAME ="HwBrkDLL.dll";
	printf("Getting LoadLibrary handle...\n");
	//Get the address of the LoadLibrary function in kernel32.dll
	LoadLibAddy =(LPVOID)GetProcAddress(GetModuleHandle("kernel32.dll"),"LoadLibraryA");
	printf("Creating remote string with the name of the DLL to be injected...\n");
	//Allocate space in the remote process to store the name of the library to be loaded.
	RemoteString =(LPVOID)VirtualAllocEx(Proc,NULL,strlen(DLL_NAME)+1,MEM_RESERVE|MEM_COMMIT,PAGE_READWRITE);
	printf("Writing string to remote memory...\n");
	//Write the name of the DLL into the allocated memory.
	WriteProcessMemory(Proc,(LPVOID)RemoteString,DLL_NAME,strlen(DLL_NAME)+1,NULL);
	printf("Creating remote thread to load DLL...\n");
	//Create a remote thread in the victim process that loads the library.
	WaitForSingleObject(CreateRemoteThread(Proc,NULL,NULL,(LPTHREAD_START_ROUTINE)LoadLibAddy,(LPVOID)RemoteString,NULL,NULL),INFINITE);
	//Free the memory we used for the string.
	VirtualFreeEx(Proc,RemoteString,strlen(DLL_NAME)+1,MEM_RELEASE);
}*/
std::string GetLastErrorAsString()
{
    //Get the error message, if any.
    DWORD errorMessageID = ::GetLastError();
    if(errorMessageID == 0)
        return std::string(); //No error message has been recorded

    LPSTR messageBuffer;
    size_t size = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
                                 NULL, errorMessageID, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&messageBuffer, 0, NULL);

    std::string message(messageBuffer, size);

    //Free the buffer.
    LocalFree(messageBuffer);

    return message;
}
void ReadProcessBYTES(HANDLE hProcess, DWORD lpAddress, void* buf, int len)
{
   DWORD oldprot, dummy = 0;
   if(VirtualProtectEx(hProcess, (void*) lpAddress, len, PAGE_READWRITE, &oldprot)==0)
   {
   std::string tmp=GetLastErrorAsString();
   printf("VirtualProtectEx error:",tmp.c_str(),"\n");
   }

   if (!ReadProcessMemory(hProcess, (void*) lpAddress, buf, len, 0))
   {
	   printf("ReadProcessMemory error\n");
   }

   if(VirtualProtectEx(hProcess, (void*) lpAddress, len, oldprot, &dummy)==0)
   {
   std::string tmp=GetLastErrorAsString();
   printf("VirtualProtectEx error:",tmp.c_str(),"\n");
   }
}

void ReadProcessBYTES2(HANDLE hProcess, DWORD lpAddress, void* buf, int len)
{
   DWORD oldprot, dummy = 0;
   if(VirtualProtect((void*) lpAddress, len, PAGE_READWRITE, &oldprot)==0)
   {
   std::string tmp=GetLastErrorAsString();
   printf("VirtualProtectEx error: %s \n",tmp.c_str());
   }

   if (!ReadProcessMemory(hProcess, (void*) lpAddress, buf, len, 0))
   {
	   printf("ReadProcessMemory error\n");
   }

   if(VirtualProtect((void*) lpAddress, len, oldprot, &dummy)==0)
   {
   std::string tmp=GetLastErrorAsString();
   printf("VirtualProtectEx error: %s \n",tmp.c_str());
   }
}

void ModifyValues(HANDLE Proc)
{ 
	WaitForSingleObject(hwbrkEvent,INFINITE);
	void* address = (void*)0x00df5435;
	unsigned int address2 = 0x00df5435;
	const int nSize = 8;
	unsigned char num_char[nSize];
	//char num_char2[1];
	//unsigned long num;
	//unsigned long long num2;
	BYTE data[] = {0x2E, 0xF4, 0xA9, 0xA0};
    DWORD dataSize = sizeof(data);
	ReadProcessMemory(Proc,(void*)address,&num_char,sizeof(num_char),0);
//ReadProcessBYTES(Proc,(DWORD)address,&num_char,sizeof(num_char));
	//ReadProcessMemory(Proc,(void*)address,num_char2,nSize,0);
	//ReadProcessMemory(Proc,(void*)address,&num,nSize,0);
//char converted[nSize*2 + 1];
  for (int i = 0; i < nSize; i++) {
  printf("%x", num_char[i]);
  //converted[i*2]<<std::hex<<num_char[i];
}
printf("\n");
	//printf("0x%llx\n", num2+ 2 ^ 32);
	//ReadProcessMemory(Proc,(void*)address,num2,nSize,0);
	//ReadProcessBYTES(Proc,address,num_char,nSize);
	//printf("before: %d \n",value);
	//WriteProcessMemory(Proc,(LPVOID)0x0019ff24,&data,dataSize,NULL);
	//ReadProcessMemory(Proc,(void*)address,&value,sizeof(value),0);
//ReadProcessMemory(Proc,(void*)address,num_char,4,0);
	//printf("after: %d \n",value);
	//WaitForSingleObject(CreateRemoteThread(Proc,NULL,NULL,(LPTHREAD_START_ROUTINE)NULL,(LPVOID)"hwbrkEvent",NULL,NULL),INFINITE);
SetEvent(hwbrkEvent2);
	printf("Creating remote thread to load DLL...\n");
}

HwBrk.h:


// 
#ifndef _HWBRK_H
#define _HWBRK_H

enum HWBRK_TYPE
{
	HWBRK_TYPE_CODE,
	HWBRK_TYPE_READWRITE,
	HWBRK_TYPE_WRITE,
	HWBRK_TYPE_EXECUTE,
};

enum HWBRK_SIZE
{
	HWBRK_SIZE_1,
	HWBRK_SIZE_2,
	HWBRK_SIZE_4,
	HWBRK_SIZE_8,
};

HANDLE SetHardwareBreakpoint(HANDLE hThread,HWBRK_TYPE Type,HWBRK_SIZE Size,void* s);
bool RemoveHardwareBreakpoint(HANDLE hBrk);


#endif

 

I just noticed, that noone else uses HWBRK_TYPE_EXECUTE, is this even a thing or I made it up and should use TYPE_CODE instead?

 

What I'm trying to do:

-create a process without starting it

-set a HW breakpoint at given address

-start process

-trigger the breakpoint and pause execution

-modify it's memory values

-resume process

  • Like 1

Share this post


Link to post
mrexodia

I see what you are trying to do, but how do you plan on receiving a notification for the hardware breakpoint without injecting a DLL with an exception handler in the process?

You can find some source code I wrote for an Enigma loader here, but it requires you to inject this as a DLL in the process. What I advise is write EBFE to the entry point of the process, create a remote thread that injects this DLL and then make that DLL restore the original bytes (or signal your loader to restore the bytes). The problem with the suspended state of a process is that lots of things don't work yet. I think the entry point of the started process is somewhere in EDX or something when you start a process suspended.

Share this post


Link to post
kincses
2 hours ago, mrexodia said:

I see what you are trying to do, but how do you plan on receiving a notification for the hardware breakpoint without injecting a DLL with an exception handler in the process?

Thought the process would enter a special state that would be detectable for the parent process, or just wait it out I guess... didn't really want to mess with its memory or flow more than needed. Seems that was a mistake.

Just to make sure I'm back on the right track:

I have to make 2 projects:

- 1 loader, which will launch the process, mess with the EP and do the injection

- 1 exception handler that gets injected into the process as a DLL and actually does the patching

Is that right?

Edited by kincses (see edit history)

Share this post


Link to post
mrexodia

Yes, or alternatively you could use CreateProcess with the DEBUG_ONLY_THIS_PROCESS flag to receive debug events. This might be problematic if your target has anti-debug detection though, I would recommend doing it the DLL injection route.

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  
×
×
  • Create New...