How to properly get contents of DLL file for PE parsing? - file

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

Related

File replacing in linux kernel

I need to replace a file with another one on a VFS (having both struct file) in a Linux kernel module. I tried 2 ways of doing that but both have some problems.
So I have 2 files correctly initialized, the first solution was:
vfs_truncate(&filp_one->f_path, 0);
err = vfs_copy_file_range(filp_two, 0, filp_one, 0, file_size, 0);
where file_size is the size of filp_two, I need the truncate because if the size of filp_one is bigger than filp_two I could have a dirty copy.
In this case, the problem is that another process can modify the file between the two operations and if I try to lock with:
inode_lock(filp_one->f_inode);
vfs_truncate(&filp_one->f_path, 0);
err = vfs_copy_file_range(filp_two, 0, filp_one, 0, file_size, 0);
inode_unlock(filp_one->f_inode);
the result is a deadlock.
The other solution and maybe better I thought was to rename filp_two and then unlink.
vfs_rename(parent, filp_two_dentry , parent, filp_one_dentry, NULL, RENAME_WHITEOUT);
I also locked with rename_lock, but I omitted because that's not the point.
In this case, the problem is that all the other open file structs after one rename will return an error "already freed". So I wanted to know if exists a way to update the file descriptors avoiding close and open again.
Looking into the source I saw the d_move function d_move, so I added this line, but nothing changes:
d_exchange(filp_one_dentry, filp_two_dentry);
Thanks for your attention and sorry for my English
P.S. I know that is not preferable to work with files in this way

Check if a file is being written using Win32 API or C/C++. I do not have write access myself

Inside a Windows C/C++ programm, I need to process a text file. So I just need to open the file for reading. However, I do not want to do that while the file is still being written to by another process. I also know that this other process will eventually close the file and never write to it agin.
Looking at similar questions on stackoverflow, the typical answer is "try and open the file for writing - if that fails then try again later").
Now in this case, my process does not have write access to the file at all. So checking if the file can be opened for writing is not an option . It will always fail irrespective of any other process having write access or not.
As Hans Passant and Igor Tandetnik said you just need to pass the appropriate sharing flag to CreateFile. As the MSDN documentation for CreateFile says:
FILE_SHARE_WRITE 0x00000002
Enables subsequent open operations on a file or device to request write access.
Otherwise, other processes cannot open the file or device if they request write access.
If this flag is not specified, but the file or device has been opened for write access
or has a file mapping with write access, the function fails.
You'll want to use code like the following:
HANDLE handle = CreateFile(name, GENERIC_READ, FILE_SHARE_READ, NULL,
OPEN_EXISTING, 0, NULL);
if (handle == INVALID_HANDLE_VALUE) {
DWORD errcode = GetLastError();
if (errcode == ERROR_SHARING_VIOLATION) {
printf("%s: sharing violation\n", name);
} else {
printf("%s: CreateFile failed, error code = %lu\n", name, errcode);
}
} else {
printf("%s: CreateFile succeeded\n", name);
}
This code in unable to tell if the ERROR_SHARING_VIOLATION occurred because the other process has the file open for writing or because the another process didn't use FILE_SHARE_READ when opening the file. In the later case any attempt to read from the file will fail with a sharing violation. The FILE_SHARE_READ flag is passed to prevent sharing violations in the case when the file already been opened and FILE_SHARE_READ was used. You could also add FILE_SHARE_DELETE but I assume you'd consider that the same as write access.

Execute a mapped file on Windows

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.

WinAPI Named Pipe location

HANDLE pipe = CreateFile( L"\\\\.\\pipe\\my_pipe",
GENERIC_READ, // only need read access
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL );
I'm new to win api and i'd like to know where is the "my_pipe" file created on the hard disk?
I can't find it anywhere near the binary or sources
Windows doesn't follow the UNIX philosophy "everything is a file", so the named objects you create with the kernel APIs aren't files, but are objects in various NT objects namespaces. You can see them with tools like WinObj.
You may want to have a look at the article about the object manager in Windows.

How can I make the printer work in C in MS VC++ Express edition?

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.

Resources