ImageBaseAddress in PEB is wrong - winapi

I'm currently trying to retrieve the Image Base Address of a suspended 32-bits process.
I successfully retrieved the PEB VA by using (*CTX).Ebx - 0x1000 (where CTX is the CONTEXT structure retrieved with GetThreadContext()), it's in correlation with the data I got from some process analysis tools.
The problem is that the field ImageBaseAddress at offset 0x08 is equal to 0xffffffff.
I verified and all the other fields are okay, if for example I create the process in debug mode the BeingDebugged byte is set to 1 etc...
And if I look with some tools where the Image of the PE is loaded I see that it's at 0x880000, unfortunately that data isn't present in the PEB.
So I basically tried to create a "normal" process that isn't suspended but I have the same problem.
All the fiels of the PEB are fine, the process too, there's just that 32-bits integer at offset 0x08 that is equal to 0xffffffff for some mysterious reasons.
(P.S.: I know that the PEB isn't documented and that it is not a great idea to depend of it as it's fields might change in the future but I really need to get the Image Base Address of a suspended process from it's PEB).
Thanks.

Use NtQueryInformationProcess with the ProcessBasicInformation, the resulting PROCESS_BASIC_INFORMATION structure will contain the correct peb address.
typedef NTSTATUS(__stdcall* tNtQueryInformationProcess)
(
HANDLE ProcessHandle,
PROCESSINFOCLASS ProcessInformationClass,
PVOID ProcessInformation,
ULONG ProcessInformationLength,
PULONG ReturnLength
);
PEB GetPEBExternal(HANDLE hProc)
{
PROCESS_BASIC_INFORMATION pbi;
PEB peb = { 0 };
tNtQueryInformationProcess NtQueryInformationProcess =
(tNtQueryInformationProcess)GetProcAddress(GetModuleHandle("ntdll.dll"), "NtQueryInformationProcess");
NTSTATUS status = NtQueryInformationProcess(hProc, ProcessBasicInformation, &pbi, sizeof(pbi), 0);
if (NT_SUCCESS(status))
{
ReadProcessMemory(hProc, pbi.PebBaseAddress, &peb, sizeof(peb), 0);
}
return peb;
}
PEB peb = GetPEBExternal(hProc);
std::cout << "0x" << std::hex << peb.ImageBaseAddress << std::endl;
Use the PEB definition from x64dbg source code, it's the best source for undocumented structures in my experience.

Related

Getting DTR and RTS pin of serial port in C on Windows platform

How to get DTR and RTS status of serial port on a windows platform? I want to read the current state (ON or OFF) of these two pins.
I can set pins with :
EscapeCommFunction(hSerial,SETRTS);
But I don't know how to read the pin status.
Since on Linux, it can be done with the following code, I assume it is technicaly feasable:
int status=0;
ioctl(fd, TIOCMGET, &status);
return status & TIOCM_RTS;
Using inc\api\ntddser.h API and winioctl.h, you can access DTR and RTS status. Call DeviceIoControl, set the second parameter to IOCTL_SERIAL_GET_DTRRTS:
Call:
DeviceIoControl(
handle, // handle returned by CreateFile
IOCTL_SERIAL_GET_DTRRTS,
NULL,
0,
&Status, // pointer to a DWORD variable 1
sizeof(Status),
&unused, // pointer to a DWORD variable
pOverlapped // optional pointer to overlapped buffer (may be NULL)
);
Documentation about DeviceIoControl here.
Unless you are actively changing the signal line, is the value set in DCB used?
Other than that, you control the signal line yourself, so you should remember it each time you change it.
As long as you have the serial port open, you have all control and nothing else will change.
Isn't there anybody who uses handshake or toggle mode now?
SetDefaultCommConfigW function
BOOL SetDefaultCommConfigW(
LPCWSTR lpszName,
LPCOMMCONFIG lpCC,
DWORD dwSize
);
SetCommConfig function
BOOL SetCommConfig(
HANDLE hCommDev,
LPCOMMCONFIG lpCC,
DWORD dwSize
);
GetCommConfig function
BOOL GetCommConfig(
HANDLE hCommDev,
LPCOMMCONFIG lpCC,
LPDWORD lpdwSize
);
COMMCONFIG structure
typedef struct _COMMCONFIG {
...
DCB dcb;
...
} COMMCONFIG, *LPCOMMCONFIG;
DCB structure
typedef struct _DCB {
DWORD DCBlength;
...
DWORD fDtrControl : 2;
...
DWORD fRtsControl : 2;
...
} DCB, *LPDCB;
DTR_CONTROL_DISABLE 0x00
DTR_CONTROL_ENABLE 0x01
DTR_CONTROL_HANDSHAKE 0x02
RTS_CONTROL_DISABLE 0x00
RTS_CONTROL_ENABLE 0x01
RTS_CONTROL_HANDSHAKE 0x02
RTS_CONTROL_TOGGLE 0x03
If you still want to do so, use DeviceIoControl() commented by #Hans Passant.
However, there is no guarantee that it is properly supported, since most people will not use it.
Device Input and Output Control (IOCTL)
DeviceIoControl function
The following is a sample DeviceIoControl call for a DISK drive, but you can call it by changing each of these parameters to those related to IOCTL_SERIAL_GET_DTRRTS for the serial port.
Calling DeviceIoControl
Serial Device Control Requests
IOCTL_SERIAL_GET_DTRRTS IOCTL

PEB_LDR_DATA structure has different members and sizes

The PEB structure contains process information and the pointer of PEB_LDR_DATA structure which contains information about the loaded modules for the process is one of PEB members.
From MSDN, PEB structure syntax is as follows:
typedef struct _PEB {
BYTE Reserved1[2];
BYTE BeingDebugged;
BYTE Reserved2[1];
PVOID Reserved3[2];
PPEB_LDR_DATA Ldr; <-- I'm curious about this one.
PRTL_USER_PROCESS_PARAMETERS ProcessParameters;
BYTE Reserved4[104];
PVOID Reserved5[52];
PPS_POST_PROCESS_INIT_ROUTINE PostProcessInitRoutine;
BYTE Reserved6[128];
PVOID Reserved7[1];
ULONG SessionId;
} PEB, *PPEB;
After searching for the structure, I found that there are various forms and they make me confused:
// Form #1: this is described in MSDN
typedef struct _PEB_LDR_DATA { // 28 bytes
BYTE Reserved1[8];
PVOID Reserved2[3];
LIST_ENTRY InMemoryOrderModuleList;
} PEB_LDR_DATA, *PPEB_LDR_DATA;
// Form #2
typedef struct _PEB_LDR_DATA { // 40 bytes
DWORD dwLength;
DWORD dwInitialized;
LPVOID lpSsHandle;
LIST_ENTRY InLoadOrderModuleList;
LIST_ENTRY InMemoryOrderModuleList;
LIST_ENTRY InInitializationOrderModuleList;
LPVOID lpEntryInProgress;
} PEB_LDR_DATA, *PPEB_LDR_DATA;
// Form #3
typedef struct _PEB_LDR_DATA { // 36 bytes
ULONG Length;
BOOLEAN Initialized;
PVOID SsHandle;
LIST_ENTRY InLoadOrderModuleList;
LIST_ENTRY InMemoryOrderModuleList;
LIST_ENTRY InInitializationOrderModuleList;
} PEB_LDR_DATA, *PPEB_LDR_DATA;
How could they have different members and sizes?
These are essentially internal undocumented data structures that can change between versions and even service packs. In the beginning only the first few fields of the TEB/TIB were semi-documented because they are used by compilers to implement SEH and TLS.
Over time people figured out some of the other fields and started using them which essentially forced Microsoft to document them. All other members have reserved names because Microsoft does not want you to use them because there might be a documented API for it or it might change in the future.
On 32-bit Windows 8 the PEB_LDR_DATA struct looks like this:
0x000 Length : Uint4B
0x004 Initialized : UChar
0x008 SsHandle : Ptr32 Void
0x00c InLoadOrderModuleList : _LIST_ENTRY
0x014 InMemoryOrderModuleList : _LIST_ENTRY
0x01c InInitializationOrderModuleList : _LIST_ENTRY
0x024 EntryInProgress : Ptr32 Void
0x028 ShutdownInProgress : UChar
0x02c ShutdownThreadId : Ptr32 Void
Symbols are not always 100% correct but it is often the best source when dealing with these types of structs. This matches the memory layout of the structs you posted (except for Form #2 which incorrectly uses DWORD for the BOOLEAN). Accessing anything beyond the LIST_ENTRYs must be done after you have checked the length member (or the Windows version) because they don't exist in older versions.
The size can be different because new fields have been added over time. The members can be different because the field actually changed over time but more likely it is a bug because somebody just used a different name/type for a field.
If your goal is to list the loaded modules then you can use the documented ToolHelp API instead...

Why can't get process id that more than 65535 by 'ntQuerySystemInformation' in Win7 64bit?

I used the 'ntQuerySystemInformation' to get all the handle information like:
NtQuerySystemInformation(SystemHandleInformation, pHandleInfor, ulSize,NULL);//SystemHandleInformation = 16
struct of pHandleInfor is:
typedef struct _SYSTEM_HANDLE_INFORMATION
{
ULONG ProcessId;
UCHAR ObjectTypeNumber;
UCHAR Flags;
USHORT Handle;
PVOID Object;
ACCESS_MASK GrantedAccess;
} SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION;
It works well in xp 32bit, but in Win7 64bit can only get the right pid that less than 65535. The type of processId in this struct is ULONG, I think it can get more than 65535. What's wrong with it? Is there any other API instead?
There are two enum values for NtQuerySystemInformation to get handle info:
CNST_SYSTEM_HANDLE_INFORMATION = 16
CNST_SYSTEM_EXTENDED_HANDLE_INFORMATION = 64
And correspondingly two structs: SYSTEM_HANDLE_INFORMATION and SYSTEM_HANDLE_INFORMATION_EX.
The definitions for these structs are:
struct SYSTEM_HANDLE_INFORMATION
{
short UniqueProcessId;
short CreatorBackTraceIndex;
char ObjectTypeIndex;
char HandleAttributes; // 0x01 = PROTECT_FROM_CLOSE, 0x02 = INHERIT
short HandleValue;
size_t Object;
int GrantedAccess;
}
struct SYSTEM_HANDLE_INFORMATION_EX
{
size_t Object;
size_t UniqueProcessId;
size_t HandleValue;
int GrantedAccess;
short CreatorBackTraceIndex;
short ObjectTypeIndex;
int HandleAttributes;
int Reserved;
}
As You can see, the first struct really can only contain 16-bit process id-s...
See for example ProcessExplorer project's source file ntexapi.h for more information.
Note also that the field widths for SYSTEM_HANDLE_INFORMATION_EX in my struct definitions might be different from theirs (that is, in my definition some field widths vary depending on the bitness), but I think I tested the code both under 32-bit and 64-bit and found it to be correct.
Please recheck if necessary and let us know if You have additional info.
From Raymond Chen's article Processes, commit, RAM, threads, and how high can you go?:
I later learned that the Windows NT folks do try to keep the numerical values of process ID from getting too big. Earlier this century, the kernel team experimented with letting the numbers get really huge, in order to reduce the rate at which process IDs get reused, but they had to go back to small numbers, not for any technical reasons, but because people complained that the large process IDs looked ugly in Task Manager. (One customer even asked if something was wrong with his computer.)

Unable to write to process memory

I am trying to fix a problem in code I am not familiar with. I have traced it down to call to WriteProcessMemory always failing with ERROR_INVALID_ADDRESS. I have no idea why it fails.I tried to check if my process has the required access to write to its child process using VirtualQUery and it does. Can anyone shed some light on this? The code path is extremely convoluted so I have skipped a lot of it. Please let me know if left out any info.
CreateProcessAsUserW(hToken, exe, cmd_line,
NULL, // No security attribute.
NULL, // No thread attribute.
false, // do not inherit handles
CREATE_SUSPENDED | CREATE_UNICODE_ENVIRONMENT | DETACHED_PROCESS | EXTENDED_STARTUPINFO_PRESENT | CREATE_BREAKAWAY_FROM_JOB, // start suspended, extended startup info, break out of job
NULL, // Use the environment of the caller
NULL, // Use current directory of the caller.
&si,
&pi);
/*
....lots of work here
*/
void* address = {...};
void* var = address; // note this line
SIZE_T written;
if(!WriteProcessMemory( pi.handle,
var, address, // not completely sure what it is doing here - writing contents of address to address of var?
size, &written))
{
DWORD error = GetLastError(); // ERROR_INVALID_ADDRESS
MEMORY_BASIC_INFORMATION buffer;
SIZE_T num = VirtualQuery(address,&buffer,sizeof(MEMORY_BASIC_INFORMATION));
if(num > 0)
{
DWORD access = buffer.AllocationProtect; // PAGE_EXECUTE_WRITECOPY
DWORD state = buffer.State; // MEM_COMMIT
DWORD type = buffer.Type;
}
}
This is a 32-bit process running on 64-bit Win7.
You're performing a local VirtualQuery before trying to write into another process, whose address space may be wildly different.
If you want to be sure to have a valid pointer in that process's adress space, either you find where that process puts what interests you (good luck with ASLR), or you allocate some memory for you within that process (with, say VirtualAllocEx()).
Note: If you actually want shared memory, you should use CreateFileMapping(INVALID_HANDLE_VALUE) instead.

How to get the imagesize of DLL from its baseaddress correctly?

I only have the base address of a DLL loaded into memory of another process. I want to get the imagesize of the DLL. So I get MEMORY_BASIC_INFORMATION from VirtualQuery. This function doesn't fail, but the allocationBase is always 0. The application crashes in the line, where you can read "bug".
Questions: Does VirtualQuery work in the given situation? Is there a better way to get the imagesize? But remember my situation: I want to get the imagesize of a DLL loaded into memory of another process! The DLL isn't loaded into my application, nor do I have a handle to the application at the moment(but it would be possible to get a handle).
...
DWORD baseAddress = (DWORD)me32.modBaseAddr; // base address of a DLL of other process
MEMORY_BASIC_INFORMATION mem;
if (NULL==VirtualQuery((LPCVOID)baseAddress, &mem, sizeof(mem))) {
printError( TEXT("VirtualQuery") );
return false;
}
unsigned char* allocationBase = (unsigned char*)mem.AllocationBase;
_tprintf( TEXT("\n allocationBase = %d"), allocationBase ); // 0
IMAGE_DOS_HEADER *dos = (IMAGE_DOS_HEADER*)mem.AllocationBase;
IMAGE_NT_HEADERS *pe = (IMAGE_NT_HEADERS*)((unsigned long)
dos+(unsigned long)dos->e_lfanew); // bug crashes application
size_t base_len = (size_t)pe->OptionalHeader.SizeOfImage;
// base address of a DLL of other process
The comment says it all, VirtualQuery only returns you info about virtual memory in your process, not the process that actually has this DLL loaded. You'll need to use VirtualQueryEx(), get the required process handle with OpenProcess().

Resources