Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Code Injection in Win 7 SP1 using NtCreateThreadEx

I am trying to learn how to inject code into a running process using NtCreateThreadEx. I found few tutorials online and tried the code shown below which basically tries to inject a piece of code to a a running notepad.exe. Code injection to notepad.exe was successful; however, this program crashes just after injection (i.e., after calling funNtCreateThreadEx) throwing following error:

Run-Time Check Failure #2 - Stack around the variable 'temp2' was corrupted.

Could someone help me explaining why I am getting this error? I tried to Google about this error and figured out its something related to memory overflow. However, I don't see any memory overflow in this following code. Please let me know what could be the reason for the above error. Thank you so much for your time.


<code>HANDLE NtCreateThreadEx(HANDLE process, LPTHREAD_START_ROUTINE Start, LPVOID lpParameter);

typedef NTSTATUS(WINAPI *LPFUN_NtCreateThreadEx)
(
OUT PHANDLE hThread,
IN ACCESS_MASK DesiredAccess,
IN LPVOID ObjectAttributes,
IN HANDLE ProcessHandle,
IN LPTHREAD_START_ROUTINE lpStartAddress,
IN LPVOID lpParameter,
IN BOOL CreateSuspended,
IN DWORD StackZeroBits,
IN DWORD SizeOfStackCommit,
IN DWORD SizeOfStackReserve,
OUT LPVOID lpBytesBuffer
);

struct NtCreateThreadExBuffer
{
ULONG Size;
ULONG Unknown1;
ULONG Unknown2;
PULONG Unknown3;
ULONG Unknown4;
ULONG Unknown5;
ULONG Unknown6;
PULONG Unknown7;
ULONG Unknown8;
};


HANDLE NtCreateThreadEx(HANDLE process, LPTHREAD_START_ROUTINE Start, LPVOID lpParameter) {

HMODULE modNtDll = LoadLibrary(L"ntdll.dll");

if (!modNtDll) {
std::cout << "Error loading ntdll.dll" << std::endl;
return 0;
}

LPFUN_NtCreateThreadEx funNtCreateThreadEx = (LPFUN_NtCreateThreadEx)GetProcAddress(modNtDll, "NtCreateThreadEx");

if (!funNtCreateThreadEx) {
std::cout << "Error loading NtCreateThreadEx()" << std::endl;
return 0;
}
NtCreateThreadExBuffer ntbuffer;

memset(&ntbuffer, 0, sizeof(NtCreateThreadExBuffer));
DWORD temp1 = 0;
DWORD temp2 = 0;


ntbuffer.Size = sizeof(NtCreateThreadExBuffer);
ntbuffer.Unknown1 = 0x10003;
ntbuffer.Unknown2 = 0x8;
ntbuffer.Unknown3 = &temp2;
ntbuffer.Unknown4 = 0;
ntbuffer.Unknown5 = 0x10004;
ntbuffer.Unknown6 = 4;
ntbuffer.Unknown7 = &temp1;
// ntbuffer.Unknown8 = 0;

HANDLE hThread;
NTSTATUS status = funNtCreateThreadEx(
&hThread,
0x1FFFFF,
NULL,
process,
(LPTHREAD_START_ROUTINE)Start,
lpParameter,
FALSE, //start instantly
0, //null
0, //null
0, //null
&ntbuffer
);
return hThread;
}

int main()
{
int res = -1;
res = privileges(); //get all required privileges

DWORD pid = getPid(L"notepad.exe");

if (pid == 0)
return PROCESS_NOT_FOUND; //error

HANDLE p;
p = OpenProcess(PROCESS_ALL_ACCESS, false, pid);
if (p == NULL) return OPEN_PROCESS_FAILED; //error


char * mytext = "Hello by CodeCave!";
char * mycaption = "Injection result";

PARAMETERS data; //let's fill in a PARAMETERS struct
HMODULE user32 = LoadLibrary(L"User32.dll");
data.MessageBoxInj = (DWORD)GetProcAddress(user32, "MessageBoxA");
strcpy_s(data.text, mytext);
strcpy_s(data.caption, mycaption);
data.buttons = MB_OKCANCEL | MB_ICONQUESTION;

//Writing funtion to notepad memory
DWORD size_myFunc = 0x8000; //Creating more memory than required
LPVOID MyFuncAddress = VirtualAllocEx(p, NULL, size_myFunc, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
WriteProcessMemory(p, MyFuncAddress, (void*)myFunc, 0x1000, NULL);

//Parameters to the function to notepad's memory
LPVOID DataAddress = VirtualAllocEx(p, NULL, sizeof(PARAMETERS), MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
WriteProcessMemory(p, DataAddress, &data, sizeof(PARAMETERS), NULL);

//invokes injected function
HANDLE thread = NtCreateThreadEx(p, (LPTHREAD_START_ROUTINE)MyFuncAddress, DataAddress);

if (thread != 0) {
//injection completed, not we can wait it to end and free the memory

}
return 0;
}

static DWORD myFunc(PARAMETERS * myparam) {
MsgBoxParam MsgBox = (MsgBoxParam)myparam->MessageBoxInj;
int result = MsgBox(0, myparam->text, myparam->caption, myparam->buttons);
switch (result) {
case IDOK:
//your code
break;
case IDCANCEL:
//your code
break;
}
return 0;
}

int privileges() {
HANDLE Token;
TOKEN_PRIVILEGES tp;
if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &Token))
{
LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tp.Privileges[0].Luid);
tp.PrivilegeCount = 1;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
if (AdjustTokenPrivileges(Token, 0, &tp, sizeof(tp), NULL, NULL) == 0) {
return 1; //FAIL
}
else {
return 0; //SUCCESS
}
}
return 1;
}

typedef int (WINAPI* MsgBoxParam)(HWND, LPCSTR, LPCSTR, UINT);

struct PARAMETERS {
DWORD MessageBoxInj;
char text[50];
char caption[25];
int buttons;
};

DWORD myFunc(PARAMETERS * myparam);</code>
</code>
Sign In or Register to comment.