Hello fellow developers,
I'm trying to map an executable binary file on Windows and then to execute the mapped file.
So far, I managed the mapping using CreateFileMapping and MapViewOfFile.
These functions gave me a HANDLE to the mapped file and a pointer to the mapped data but I have no clue how to execute the mapped binary.
I think I should use the CreateProcess function but what should it be given as parameters ?
char *binaryPath = "C:/MyExecutable.exe";
// Get the binary size
std::fstream stream(binaryPath, std::ios::in | std::ios::binary);
stream.seekg(0, std::ios::end);
unsigned int size = stream.tellg();
// Create a mapped file in the paging file system
HANDLE mappedFile = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_EXECUTE_READ, 0, size, NULL);
// Put the executable data into the mapped file
void* mappedData = MapViewOfFile(mappedFile, FILE_MAP_READ | FILE_MAP_EXECUTE, 0, 0, size);
stream.read((char*)mapping, size);
stream.close();
// What should I do now ?
There is no native way to run a raw executable image that resides in memory. CreateProcess() is the official way to run an executable image, but the image must reside on the file system instead. The OS loads the image into memory and then patches it as needed (resolves DLL references, etc) so it will actually run correctly.
With that said, I have seen third-party code floating around that duplicates what the OS does when it loads an executable image into memory. But I've only ever seen that used with DLLs (so code does not have to use LoadLibrary/Ex() to use a DLL in memory), not with EXEs.
Related
I would like to know the mechanism in which the Linux Kernel knows which file descriptor (e.g. /dev/input/eventX) to write the input to. For example, I know that when the user clicks the mouse, an interrupt occurs, which gets handled by the driver and propagated to the Linux input core via input_event (drivers/input/input.c), which eventually gets written to the appropriate file in /dev/input/. Specifically, I want to know which source files I need to go through to see how the kernel knows which file to write to based on the information given about the input event. My goal is to see if I can determine the file descriptors corresponding to specific input event codes before the kernel writes them to the /dev/input/eventX character files.
You may go through two files:
drivers/input/input.c
drivers/input/evdev.c
In evdev.c, evdev_init() will call input_register_handler() to initialize input_handler_list.
Then in an input device driver, after initialize input_dev, it will call:
input_register_device(input_dev)
-> get device kobj path, like /devices/soc/78ba000.i2c/i2c-6/6-0038/input/input2
-> input_attach_handler()
-> handler->connect(handler, dev, id);
-> evdev_connect()
In evdev_connect(), it will do below:
1. dynamic allocate a minor for a new evdev.
2. dev_set_name(&evdev->dev, "event%d", dev_no);
3. call input_register_handle() to connect input_dev and evdev->handle.
4. create a cdev, and call device_add().
After this, you will find input node /dev/input/eventX, X is value of dev_no.
I try get IShellItem for a file to copy it with IFileOperation COM interface from system directory to another directory. I must use exactly IFileOperation COM interface for this purpose.
When I specify full filename - return value from SHCreateItemFromParsingName() was ERROR_FILE_NOT_FOUND, but file present in the directory. When I delete filename from path below and use only folder path - all seems good, return value is S_OK.
//...
CoInitialize(NULL);
//...
WCHAR szSourceDll[MAX_PATH * 2];
wcscpy_s(szSourceDll, MAX_PATH, L"C:\\Windows\\System32\\sysprep\\cryptbase.dll");
r = CoCreateInstance(&CLSID_FileOperation, NULL, CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER | CLSCTX_INPROC_HANDLER, &IID_IFileOperation, &FileOperation1);
if (r != S_OK) return;
FileOperation1->lpVtbl->SetOperationFlags(FileOperation1, FOF_NOCONFIRMATION | FOFX_NOCOPYHOOKS | FOFX_REQUIREELEVATION);
r = SHCreateItemFromParsingName(szSourceDll, NULL, &IID_IShellItem, &isrc);
//...
CoUninitialize();
//...
Why this code, written in C, not working with filenames. How can I create IShellItem instance for file in system folder to copy it?
P.S.
Windows 7 x64, C, Visual Studio 2015, v140 platform toolset, additional dependencies: Msi.lib;Wuguid.lib;ole32.lib;ntdll.lib
P.P.S
It's properly work with files in user`s directories...
Assuming your application is compiled as a 32-bit application and running on a 64-bit OS, a file not found error is probably correct because your application is redirected to the 32-bit system directory (%WinDir%\SysWoW64).
In most cases, whenever a 32-bit application attempts to access %windir%\System32, %windir%\lastgood\system32, or %windir%\regedit.exe, the access is redirected to an architecture-specific path.
For more information, see File System Redirector on MSDN.
You could temporarily turn off redirection in your thread but it is not really safe to do this when calling shell functions, only functions in kernel32. If the API you are calling internally uses LoadLibrary and/or COM then the API might fail because it will be unable to load from system32 while redirection is disabled.
You can also access the native system32 directory with the %WinDir%\SysNative backdoor. This only works in 32-bit applications on 64-bit Vista+ so you must do some version detection.
I'm trying to get the RVA of a function in kernel32.dll which means I need to use the offsets to find different structures in the file until I can get the IMAGE_EXPORT_DIRECTORY structure. However I know a lot of methods and ways of getting the contents of files interpret and leave certain characters and stuff out which would make this a nearly impossible task. So I want to know the best way to go about getting the contents of a dll file to copy into a character array.
Update: For anyone interested I created a function for mapping the dll into memory.
void* GetFileImage(char path[])
{
HANDLE hFile = CreateFile(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL);
if(hFile == INVALID_HANDLE_VALUE){return NULL;}
HANDLE file_map = CreateFileMapping(hFile, NULL, PAGE_READONLY|SEC_IMAGE, 0, 0, "KernelMap");
if(file_map == INVALID_HANDLE_VALUE){return NULL;}
LPVOID file_image = MapViewOfFile(file_map, FILE_MAP_READ, 0, 0, 0);
if(file_image == 0){return NULL;}
return file_image;
}
There are multiple ways. Not that many multiple, though.
1.If you are trying to parse a system loaded file such as kernel32.dll which are loaded into memory on system startup, you can directly use GetModuleHandle to grab the loaded base address and start parsing through PE (assuming you are familiar with the PE structure and static/delay loading of dlls and its exports).
2.If the dll you are trying to parse is not one of the system loaded, you can load them using LoadLibrary, which will return you the loaded base address, thus enabling you to parse the PE.
3.You can also do CreatFileMapping/MapViewOfFile to map the dll in your own virtual memory to parse.
The msdn article suggested by #David Thomas will be of great help:: Peering Inside the PE
I am using libhal to detect device events. I am able to detect a device added or removed but I can not detect device's mount point. The function libhal_volume_get_mount_point(volume) does not work.
I have a callback function to detect device add:
static void handle_device_added(LibHalContext *ctx, const char *udi) {
dbus_bool_t is_storage;
dbus_bool_t is_volume;
is_storage = libhal_device_query_capability(ctx, udi, "storage", NULL);
is_volume = libhal_device_query_capability(ctx, udi, "volume", NULL);
if (is_storage) {
drive = libhal_drive_from_udi(ctx, udi);
if (libhal_drive_is_hotpluggable(drive) || libhal_drive_uses_removable_media(drive)) {
printf("Storage device added %s model %s\n",
libhal_drive_get_device_file(drive),
libhal_drive_get_model(drive));
}
libhal_drive_free(drive);
}
if(is_volume) {
volume = libhal_volume_from_udi(ctx, udi);
printf("Mount point = %s\n", libhal_volume_get_mount_point(volume));
libhal_volume_free(volume);
}
}
libhal_volume_from_udi, returns NULL.
Do you know any suitable way to detect the mount point of a storage device in C?
UPDATE
I have managed to find mount point of the device by searching /etc/mtab but there is still one little problem. I am assuming the device has one partition only.
How can I get the list of the partition on a storage device? So I can found mount points of each.
First, if you provide more details on what fails when you try to use the libhal function, you may get answers that help fix that issue. But to answer your question directly, a C program can determine what is mounted where by reading /etc/mtab. The format is fairly self-explanatory, each line typically lists the name of the storage device, the directory where it is mounted, the filesystem type, and mount options.
To map a specific directory in the filesystem to the mount point it belongs to it can be a little tricky -- remember if you're looping through /etc/mtab that mount points can have other mount points beneath them.
You may find looking at the source for programs that do this correctly, like "df" will help you get it right, or if your program doesn't need to look up this information often, you might decide to simply call popen(3) on a df command to do it for you. For example, the command:df /media/my-volume/some/path does a nice job displaying both the name of the storage device and the mount point where that device is mounted.
I am using VC++ 2008 express edition for C. When I try to run this:
/* Demonstrates printer output. */
#include <stdio.h>
main()
{
float f = 2.0134;
fprintf(stdprn, "This message is printed.\n\n");
fprintf(stdprn, "And now some numbers:\n\n");
fprintf(stdprn, "The square of %f is %f.", f, f*f);
/* Send a form feed */
fprintf(stdprn, "\f");
}
I get four of these errors: error C2065: 'stdprn' : undeclared identifier.
On this forum, they wrote that it works to define the printer as follows:
FILE *printer;
printer = fopen("PRN", "w");
EDIT
It builds with a warning that fopen is unsafe. When it runs the error appears:
Debug Assertion fails.
File: f:\dd\vctools\crt_bld\self_x86\crt\src\fprintf.c
Line: 55
Expression: (str != NULL)
The stdprn stream was an extension provided by Borland compilers - as far as I know, MS have never supported it. Regarding the use of fopen to open the printer device, I don't think this will work with any recent versions of Windows, but a couple of things to try:
use PRN: as the name instead of PRN (note the colon)
try opening the specific device using (for example) LPT1: (once again, note the colon). This will of course not work if you don't have a printer attached.
don't depend on a printer dialog coming up - you are not really using the WIndows printing system when you take this approach (and so it probably won't solve your problem, but is worth a try).
I do not have a printer attached, but I do have the Microsoft XPS document writer installed, s it shoulod at least bring up the standard Windows Print dialog from which one can choose the printer.
No. It wouldn't bring up a dialogue. This is because you are flushing data out to a file. And not going through the circuitous Win32 API.
The print doesn't work because the data is not proper PDL -- something that the printer could understand. For the print to work fine, you need to push in a PDL file, with language specific constructs. This varies from printer to printer, a PS printer will need you to push in a PostScript snippet, a PCL -- a PCL command-set and in case of MXDW you will have to write up XML based page description markup and create a zip file (with all resources embedded in it) i.e. an XPS file to get proper printout.
The PDL constructs are important because otherwise the printer doesn't know where to put the data, which color to print it on, what orientation to use, how many copies to print and so on and so forth.
Edit: I am curious why you are doing this. I understand portability is probably something you are trying to address. But apart from that, I'd like to know, there may be better alternatives available. Win32 Print Subsytem APIs are something that you ought to lookup if you are trying to print programmatically on Windows with any degree of fidelity.
Edit#2:
EDIT It builds with a warning that fopen is unsafe.
This is because MS suggests you use the safer versions nowadays fopen_s . See Security Enhancements in the CRT.
When it runs the error appears:
Debug Assertion fails. File: f:\dd\vctools\crt_bld\self_x86\crt\src\fprintf.c Line: 55
Expression: (str != NULL)
This is because fopen (whose return value you do not check) returns a NULL pointer. The file open failed. Also, if it did succeed a matching fclose call is called for.
There's no such thing as stdprn in ANSI C, it was a nonstandard extension provided by some compilers many years ago.
Today to print you have to use the specific APIs provided on your platform; to print on Windows you have to use the printing APIs to manage the printing of the document and obtain a DC to the printer and the GDI APIs to perform the actual drawing on the DC.
On UNIX-like OSes, instead, usually CUPS is used.
You can substitute the printer using this command with net use, see here on the MSDN kb
NET USE LPT1 \\server_name\printer_name
There is an excellent chapter on printing in DOS using the BIOS, ok, its a bit antiquated but interesting to read purely for nostalgic sake.
Onto your problem, you may need to use CreateFile to open the LPT1 port, see here for an example, I have it duplicated it here, for your benefit.
HANDLE hFile;
hFile = CreateFile("LPT1", GENERIC_WRITE, 0,NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
// handle error
}
OVERLAPPED ov = {};
ov.hEvent = CreateEvent(0, false, false, 0);
char szData[] = "1234567890";
DWORD p;
if (!WriteFile(hFile,szData, 10, &p, &ov))
{
if (GetLastError() != ERROR_IO_PENDING)
{
// handle error
}
}
// Wait for write op to complete (maximum 3 second)
DWORD dwWait = WaitForSingleObject(ov.hEvent, 3000);
if (dwWait == WAIT_TIMEOUT)
{
// it took more than 3 seconds
} else if (dwWait == WAIT_OBJECT_0)
{
// the write op completed,
// call GetOverlappedResult(...)
}
CloseHandle(ov.hEvent);
CloseHandle(hFile);
But if you insist on opening the LPT1 port directly, error checking is omitted...
FILE *prn = fopen("lpt1", "w");
fprintf(prn, "Hello World\n\f");
fclose(prn);
Hope this helps,
Best regards,
Tom.