I'm writing optimized Windows based shellcode in C++ and I have problem avoiding hardcoded addresses in C++ while passing it to function.
e.g:
My_CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)&thread_callback, NULL, NULL, NULL);
DWORD WINAPI thread_callback(LPVOID lpParam)
{
// stuff..
}
in disassembly, it shows CreateThread(..., cardcoded_address, ..);
instead, I want to pass this address like "from this location to thread_callback"
is there any way to avoid it? (because shellcode should be address independent?)
Regards.
Anyways, I was searching/doing some stuff and the final thing I've could done is that you can solve this with delta offset.
Explanation: at the very first function of your code, there should be function like this:
DWORD delta;
__asm {
call GetBasePointer
GetBasePointer:
pop eax
sub eax, GetBasePointer
mov [delta], eax
}
You can also google for delta offset for more details.
Afterwards, you can do something like this:
My_CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)((DWORD)thread_callback + (DWORD)delta), NULL, NULL, NULL);
DWORD WINAPI thread_callback(LPVOID lpParam)
{
// stuff..
}
and it will work fine,
Regards.
Related
My goal is to intercept outbound TCP packets from a custom-built application that I do not have source code to. I need to adjust several parameters in the outbound data. It is an older application that the original company no longer sells and the developer is no longer available.
So I was planning to install an API injection trampoline into the send() type raw WinSock API from my DLL that I can inject into the target process. But before writing such DLL, I decided to test this concept in my local process. So I did the following:
#ifdef _M_X64
//Simple code to install "API injection trampoline"
//Compiled as 64-bit process
static int WINAPI TestJump1(SOCKET s, const char *buf, int len, int flags);
{
//This part is just for debugging to make sure that my trampoline method is called
//The actual "working" trampoline will involve additional steps to insure that the original method is also called
::MessageBox(NULL, L"Injected method called!", L"Debugger Message", MB_OK);
return SOCKET_ERROR;
}
HMODULE hModWS2 = ::LoadLibrary(L"Ws2_32.dll");
if(hModWS2)
{
int (WINAPI *pfn_send)(SOCKET s, const char *buf, int len, int flags);
int (WINAPI *pfn_sendto)(SOCKET s, const char *buf, int len, int flags, const struct sockaddr *to, int tolen);
if(pfn_send &&
pfn_sendto)
{
//Long absolute JMP
//48 b8 xx xx xx xx xx xx xx xx mov rax, 0xxxx
//ff e0 jmp rax
BYTE subst[] = {
0x48, 0xb8,
0, 0, 0, 0,
0, 0, 0, 0,
0xff, 0xe0
};
HANDLE hProc = ::GetCurrentProcess();
VOID* pPtrAPI = pfn_send;
//Also tried with
//VOID* pPtrAPI = pfn_sendto;
//Make this address writable
DWORD dwOldProtect = 0;
if(::VirtualProtectEx(hProc, pPtrAPI, sizeof(subst), PAGE_EXECUTE_READWRITE, &dwOldProtect))
{
//Install JMP opcodes
VOID* pJumpPtr = TestJump1;
*(VOID**)(subst + 2) = pJumpPtr;
memcpy(pPtrAPI, subst, sizeof(subst));
//Reset it back
DWORD dwDummy;
if(::VirtualProtectEx(hProc, pPtrAPI, sizeof(subst), dwOldProtect, &dwDummy))
{
if(::FlushInstructionCache(hProc, pPtrAPI, sizeof(subst)))
{
//Try to call our method
//int rz = pfn_send(NULL, "", 0, 0); //This works!
//Try real test with the higher level API
//Download a web page into a file:
//This API must be calling raw sockets at some point internally...
//but my TestJump1() is never called from here...
HRESULT hr = URLDownloadToFile(NULL,
L"http://microsoft.com/",
L"C:\\Users\\User\\Desktop\\file.txt", 0, NULL);
}
}
}
}
}
#endif
So the code works fine, the JMP trampoline is installed and called alright if I call send method explicitly (as shown above) but my further assumption that a higher level API (i.e. URLDownloadToFile) would call it as well does not seem to hold true. My trampoline method is never called from it.
So what am I missing here? Is there an even lower WinSock API?
send() is not the only function available for sending TCP data using Winsock in user code. There is also:
WSASend()
WSASendDisconnect()
WSASendMsg()
TransmitFile()
TransmitPackets()
RIOSend/Ex()
At the very least, apps that don't use send() will usually use WSASend() instead, for use with Overlapped I/O or I/O Completion Ports. That is usually good enough for most situations. The other functions are not used very often, but may be used in certain situations where higher performance is really needed.
the lowest level winsock api is implemented by Winsock Service Provider Interface. during interface initialization the WSPStartup function is called from interface provider (this api must be exported by name from provider dll). for MSAFD Tcpip [TCP/IP] "{E70F1AA0-AB8B-11CF-8CA3-00805F48A192}" it implemented in mswsock.dll by default - look more here (strictly said used dll registered in HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Services\WinSock2\Parameters\Protocol_Catalog9\Catalog_Entries[64] but by default, this is mswsock.dll )
WSPStartup return to ws2_32 WSPPROC_TABLE - here the lowest user mode api which called. say for sendto - this is lpWSPSendTo function. so for hook all sendto you need replace lpWSPSendTo pointer in WSPPROC_TABLE to own. some api pointers returned via WSPIoctl. so you must replace lpWSPIoctl member in table to own and replace in result returned by original WSPIoctl to own api. example for RIO extension:
#include <ws2spi.h>
#include <mswsock.h>
LPWSPIOCTL g_lpWSPIoctl;
LPWSPSENDTO g_lpWSPSendTo;
LPFN_RIOSENDEX g_RIOSendEx;
int WSPAPI WSPIoctl(
__in SOCKET s,
__in DWORD dwIoControlCode,
__in LPVOID lpvInBuffer,
__in DWORD cbInBuffer,
__out LPVOID lpvOutBuffer,
__in DWORD cbOutBuffer,
__out LPDWORD lpcbBytesReturned,
__in LPWSAOVERLAPPED lpOverlapped,
__in LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
__in LPWSATHREADID lpThreadId,
__out LPINT lpErrno
)
{
int r = g_lpWSPIoctl(s, dwIoControlCode, lpvInBuffer, cbInBuffer, lpvOutBuffer, cbOutBuffer, lpcbBytesReturned, lpOverlapped, lpCompletionRoutine, lpThreadId, lpErrno);
static GUID functionTableId = WSAID_MULTIPLE_RIO;
if (
!r
&&
dwIoControlCode == SIO_GET_MULTIPLE_EXTENSION_FUNCTION_POINTER &&
cbInBuffer == sizeof(GUID) &&
cbOutBuffer >= sizeof(RIO_EXTENSION_FUNCTION_TABLE) &&
!memcmp(lpvInBuffer, &functionTableId, sizeof(GUID))
)
{
PRIO_EXTENSION_FUNCTION_TABLE priot = (PRIO_EXTENSION_FUNCTION_TABLE)lpvOutBuffer;
if (priot->cbSize >= FIELD_OFFSET(RIO_EXTENSION_FUNCTION_TABLE, RIOSendEx))
{
g_RIOSendEx = priot->RIOSendEx;// save original pointer to use
priot->RIOSendEx = RIOSendEx;// this is your hook function
}
}
return r;
}
so we need hook WSPStartup function before it will be called first time by ws2_32.dll
I am using mmsystem.h to read joystick data in windows. Following strucure is used for reading
typedef struct joyinfoex_tag {
DWORD dwSize;
DWORD dwFlags;
DWORD dwXpos;
DWORD dwYpos;
DWORD dwZpos;
DWORD dwRpos;
DWORD dwUpos;
DWORD dwVpos;
DWORD dwButtons;
DWORD dwButtonNumber;
DWORD dwPOV;
DWORD dwReserved1;
DWORD dwReserved2;
} JOYINFOEX
JOYINFOEX joyInfoEx;
joyGetPosEx(0, &joyInfoEx);
I want to send force feedback to the joystick. Can any one help me to do this ?
Based on the available documentation, there does not seem to be direct support for controller FeedBack via the mmsystem interface.
I'm studying dll injection and so far I managed to inject a dll in a process causing the message box to show up.
The part I didn't quite understand, even after tons of readings and research, is how I pass a parameter to the dll, or call a specific function within it.
The dll:
extern "C" __declspec(dllexport) bool WINAPI
DllMain(HINSTANCE hInstDll, DWORD fdwReason, LPVOID lpvReserved)
{
switch (fdwReason)
{
case DLL_PROCESS_ATTACH:
{
MessageBoxA(NULL, "Hello World!", "Dll says:", MB_OK);
break;
}
case DLL_PROCESS_DETACH:
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
}
return true;
}
The injection:
char dllPath[] = "sampleDll.dll";
// For dll path injection.
int memAmountToAllocate = strlen(dllPath);
LPVOID dllPathAddress = VirtualAllocEx(procHandle, 0, memAmountToAllocated, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
FARPROC loadLibraryAddr = GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA");
WriteProcessMemory(procHandle, dllPathAddress, dllPath, memAmountToAllocated, 0);
// creating a thread that will call LoadLibraryA with allocMemAddress as argument
CreateRemoteThread(procHandle, 0, 0, loadLibraryAddr, dllPathAddress, 0, 0);
As I said, the injection works fine, i.e. the message box appears.
But say I have a method in the dll foo(LPVOID ptrToData). How can I call the foo function?
I have the address of the function I want to execute on the target process, it is an adding function, so I need to pass x and y.
I can call the function like this
_asm
{
push 0;
push 0x7;
mov ecx, esi;
mov eax, 0x41367C;
call eax;
}
however the values for push must come from the injecting process.
How can I do that?
The solution to my problem was to use an IPC mechanism to allow my main application and dll to communicate.
I used a named pipe.
I created the pipe in C# and then when I inject the dll I connect to the pipe.
I tried to get the main thread id of a another process, like it was suggested here:
https://stackoverflow.com/a/8058710/1386873
DWORD GetMainThreadId(DWORD dwPid)
{
LPCVOID lpTid;
_asm
{
mov eax, fs:[18h]
add eax, 36
mov lpTid, eax
}
HANDLE hProcess = OpenProcess(PROCESS_VM_READ, FALSE, dwPid);
if (hProcess == NULL)
return NULL;
int dwTid = 0;
if (ReadProcessMemory(hProcess, lpTid, (LPVOID)&dwTid, sizeof(int), NULL) == FALSE)
{
CloseHandle(hProcess);
return NULL;
}
CloseHandle(hProcess);
return (DWORD)dwTid;
}
But this does not work: ReadProcessMemory always returns a 299 Code from GetLastError(), which means "ERROR_PARTIAL_COPY - Only part of a ReadProcessMemory or WriteProcessMemory request was completed.". Well the error message is pretty clear, but why does this happen? BytesRead are also always 0.
I get the process id like this:
unsigned long GetTargetProcessIdFromWindow(LPCWSTR className, LPCWSTR windowName)
{
unsigned long processID = 0;
HWND targetWnd;
targetWnd = FindWindow(className, windowName);
GetWindowThreadProcessId(targetWnd, &processID);
return processID;
}
which seems to be working fine. What might cause this? I tried different applications (Calculator, Notepad etc.). My application is build for Win32, my operating system is Windows 64bit.
Does this have to do with the TIB? As far as i understand it, as long as i build it for Win32 the way i do it should be fine, shouldn't it.
Thanks for any tips.
Consider Toolhlp functions instead - CreateToolhelp32Snapshot() and Thread32First().
Debugging with visual studio 2005 The following Error Displayed :
Unhandled exception at 0x00000000 in procexp.exe: 0xC0000005: Access
violation reading location 0x00000000.
And Thread Information:
2704 Win32 Thread 00000000 Normal 0
extern "C" VDLL2_API BOOL WINAPI MyTerminateProcess(HANDLE hProcess,UINT uExitCode)
{
SetLastError(5);
return FALSE;
}
FARPROC HookFunction(char *UserDll,FARPROC pfn,FARPROC HookFunc)
{
DWORD dwSizeofExportTable=0;
DWORD dwRelativeVirtualAddress=0;
HMODULE hm=GetModuleHandle(NULL);
FARPROC pfnOriginalAddressToReturn;
PIMAGE_DOS_HEADER pim=(PIMAGE_DOS_HEADER)hm;
PIMAGE_NT_HEADERS pimnt=(PIMAGE_NT_HEADERS)((DWORD)pim +
(DWORD)pim->e_lfanew);
PIMAGE_DATA_DIRECTORY
pimdata=(PIMAGE_DATA_DIRECTORY)&(pimnt->OptionalHeader.DataDirectory);
PIMAGE_OPTIONAL_HEADER pot=&(pimnt->OptionalHeader);
PIMAGE_DATA_DIRECTORY
pim2=(PIMAGE_DATA_DIRECTORY)((DWORD)pot+(DWORD)104);
dwSizeofExportTable=pim2->Size;
dwRelativeVirtualAddress=pim2->VirtualAddress;
char *ascstr;
PIMAGE_IMPORT_DESCRIPTOR
pimexp=(PIMAGE_IMPORT_DESCRIPTOR)(pim2->VirtualAddress + (DWORD)pim);
while(pimexp->Name)
{
ascstr=(char *)((DWORD)pim + (DWORD)pimexp->Name);
if(strcmpi(ascstr,UserDll) == 0)
{
break;
}
pimexp++;
}
PIMAGE_THUNK_DATA
pname=(PIMAGE_THUNK_DATA)((DWORD)pim+(DWORD)pimexp->FirstThunk);
LPDWORD lpdw=&(pname->u1.Function);
DWORD dwError=0;
DWORD OldProtect=0;
while(pname->u1.Function)
{
if((DWORD)pname->u1.Function == (DWORD)pfn)
{
lpdw=&(pname->u1.Function);
VirtualProtect((LPVOID)lpdw,sizeof(DWORD),PAGE_READWRITE,&OldProtect);
pname->u1.Function=(DWORD)HookFunc;
VirtualProtect((LPVOID)lpdw,sizeof(DWORD),PAGE_READONLY,&OldProtect);
return pfn;
}
pname++;
}
return (FARPROC)0;
}
FARPROC CallHook(void)
{
HMODULE hm=GetModuleHandle(TEXT("Kernel32.dll"));
FARPROC fp=GetProcAddress(hm,"TerminateProcess");
HMODULE hm2=GetModuleHandle(TEXT("vdll2.dll"));
FARPROC fpHook=GetProcAddress(hm2,"MyTerminateProcess");
dwAddOfTerminateProcess=HookFunction("Kernel32.dll",fp,fpHook);
if(dwAddOfTerminateProcess == 0)
{
MessageBox(NULL,TEXT("Unable TO Hook Function."),TEXT("Parth"),MB_OK);
}
else
{
MessageBox(NULL,TEXT("Success Hooked."),TEXT("Parth"),MB_OK);
}
return 0;
}
Thanks in advance for any help.
004118AC mov esi,esp
004118AE push 0
004118B0 mov eax,dword ptr [hProc]
004118B3 push eax
004118B4 call dword ptr[__imp__TerminateProcess#8(4181E4h)]
004118BA cmp esi,esp
esi returned zero. why ?
What is VDLL2_API defined as? It may be interfering with the calling convention (which is meant to be WINAPI for this function, as you write it later on the same line).
Stack problems on exit (ESI, ESP) usually indicate that you have your calling conventions mixed up. You appear to have used FARPROC consistently everywhere else, but since you know the exact prototype of the function, try typedef-ing that as the type to use instead:
typedef BOOL (WINAPI *TERMINATEPROCESS_PROC)(HANDLE, UINT);
Now use TERMINATEPROCESS_PROC everywhere instead of FARPROC.
Don't write this kind of code yourself. Use the Detours library from Microsoft Research.