VOID PeFreeExportTable(DWORD *AddressTable, DWORD *NameTable, WORD *OrdinalTable) { DeallocMem(AddressTable); DeallocMem(NameTable); DeallocMem(OrdinalTable); }
BOOL PsGetImageFileNameEx(HANDLE ProcessHandle, LPVOID ModuleBase, LPWSTR FileName, SIZE_T Length, PSIZE_T ReturnLength) { NTSTATUS status = STATUS_UNSUCCESSFUL; PNT_UNICODE_STRING unicodeString; SIZE_T bufferSize; LPVOID buffer; SIZE_T retLength; bufferSize = 0x100; do { buffer = AllocMem(bufferSize); if (!buffer) { break; } status = NtQueryVirtualMemory(ProcessHandle, ModuleBase, NT_MEMORY_INFORMATION_CLASS::MemoryMappedFilenameInformation, buffer, bufferSize, &retLength); if (status == STATUS_BUFFER_OVERFLOW) { DeallocMem(buffer); bufferSize = retLength; } else { break; } } while (TRUE); if (buffer) { unicodeString = (PNT_UNICODE_STRING)buffer; wcscpy_s(FileName, Length, unicodeString->Buffer); *ReturnLength = unicodeString->MaximumLength; DeallocMem(buffer); return STATUS_UNSUCCESSFUL; } return status; }
//=================================== // Close the file represented by fcb //=================================== long CloseFile(struct FCB *fcb) { if (fcb->bufferIsDirty) WriteBlock(fcb->currentBlock, fcb->buffer); if (fcb->inodeIsDirty) PutINode(fcb->inodeNumber, fcb->inode); DeallocMem(fcb->buffer); DeallocMem(fcb->inode); DeallocMem(fcb); FlushCaches(); return 0; }
//================================================ // Read noBytes into buffer from the file fHandle //================================================ long ReadFromFile(struct FCB *fHandle, char *buffer, long noBytes) { long retval = 0; long bytesRead = 0; char done = 0; char *buff; struct Message *FSMsg; if (noBytes == 0) return 0; buff = AllocKMem(PageSize); FSMsg = ALLOCMSG; while (noBytes > PageSize) { FSMsg->nextMessage = 0; FSMsg->byte = READFILE; FSMsg->quad1 = (long) fHandle; FSMsg->quad2 = (long) buff; FSMsg->quad3 = PageSize; SendReceiveMessage(FSPort, FSMsg); copyMem(buff, buffer + bytesRead, (size_t) (FSMsg->quad1)); bytesRead += FSMsg->quad1; noBytes -= PageSize; if (FSMsg->quad1 < PageSize) done = 1; } if (!done) { FSMsg->nextMessage = 0; FSMsg->byte = READFILE; FSMsg->quad1 = (long) fHandle; FSMsg->quad2 = (long) buff; FSMsg->quad3 = noBytes; SendReceiveMessage(FSPort, FSMsg); copyMem(buff, buffer + bytesRead, (size_t) (FSMsg->quad1)); bytesRead += FSMsg->quad1; } retval = bytesRead; DeallocMem(buff); DeallocMem(FSMsg); return (retval); }
//====================================================== // Send a message to a message port and wait for a reply //====================================================== void SendReceiveMessage(struct MessagePort *MP, struct Message *Msg) { struct MessagePort *tempMP = AllocMessagePort(); Msg->tempPort = tempMP; SendMessage(MP, Msg); ReceiveMessage(tempMP, Msg); DeallocMem(tempMP); }
BOOL IpcCreateThread(IN IPC_THREAD_ROUTINE ThreadRoutine, IN BOOL CreateSuspended, IN LPVOID UserData, OUT PTHREAD *Thread) { PTHREAD NewThread = NULL; TRY(BOOL, TRUE) { if (!(NewThread = (PTHREAD)AllocMem(sizeof(THREAD)))) { LEAVE(FALSE); } InitializeCriticalSection(&NewThread->CriticalSection); NewThread->DoSafeStop = FALSE; NewThread->IsSuspended = CreateSuspended; NewThread->ThreadRoutine = ThreadRoutine; NewThread->UserData = UserData; NewThread->ObjectHandle = CreateThread(NULL, 0, IpcSystemThreadRoutine, NewThread, CREATE_SUSPENDED, &NewThread->ObjectId); if (!NewThread->ObjectHandle) { LEAVE(FALSE); } if (!CreateSuspended) { ResumeThread(NewThread->ObjectHandle); } } FINALLY { if (!TRY_VALUE && NewThread) { DeleteCriticalSection(&NewThread->CriticalSection); TerminateThread(NewThread->ObjectHandle, 0); CloseHandle(NewThread->ObjectHandle); DeallocMem(NewThread); NewThread = NULL; } } *Thread = NewThread; return TRY_VALUE; }
BOOL IpcDestroyThread(IN PTHREAD *Thread) { BOOL Result; DeleteCriticalSection(&(*Thread)->CriticalSection); Result = CloseHandle((*Thread)->ObjectHandle); Result = DeallocMem(*Thread) && Result; *Thread = NULL; return Result; }
//=============================================== // Create the directory "path" // Returns 0 on success or a negative error code //=============================================== long CreateDir(char *name) { char *parentDirectory, *fileName; u_int32_t parentINodeNo, group; struct ext2_dir_entry_2 *newEntry; struct ext2_inode parentINode; struct FCB *fcb = CreateFileWithType(name, EXT2_FT_DIR); if (!fcb) return -ENOENT; // Get inode number of parent directory parentDirectory = AllocUMem((size_t)strlen(name) + 1); strcpy(parentDirectory, name); fileName = strrchr(parentDirectory, '/'); fileName[0] = 0; parentINodeNo = GetFileINode(parentDirectory); DeallocMem(parentDirectory); newEntry = AllocUMem(sizeof(struct ext2_dir_entry_2)); memset(newEntry, 0, sizeof(struct ext2_dir_entry_2)); newEntry->file_type = EXT2_FT_DIR; newEntry->inode = fcb->inodeNumber; fcb->inode->i_links_count++; newEntry->name_len = 1; newEntry->rec_len = 12; newEntry->name[0] = '.'; (void)WriteFile(fcb, (char *) newEntry, 12); newEntry->inode = parentINodeNo; GetINode(parentINodeNo, &parentINode); parentINode.i_links_count++; PutINode(parentINodeNo, &parentINode); newEntry->name_len = 2; newEntry->rec_len = 0x3F4; newEntry->name[1] = '.'; (void)WriteFile(fcb, (char *) newEntry, 12); group = fcb->inodeNumber / sb.s_inodes_per_group; group_descriptors[group].bg_used_dirs_count++; fcb->inode->i_mode = (u_int16_t)(EXT2_S_IFDIR | EXT2_S_IRUSR | EXT2_S_IWUSR | EXT2_S_IXUSR | EXT2_S_IRGRP | EXT2_S_IXGRP | EXT2_S_IROTH | EXT2_S_IXOTH); fcb->inode->i_size = (u_int32_t)block_size; (void)CloseFile(fcb); return 0; }
//====================================== // Receive a message from a message port //====================================== void ReceiveMessage(struct MessagePort *MP, struct Message *Msg) { struct Message *temp; while (MP->msgQueue == 0) { MP->waitingProc = currentTask; currentTask->waiting = 0x80; BlockTask(currentTask); SWTASKS; } asm("cli"); temp = MP->msgQueue; MP->msgQueue = temp->nextMessage; temp->nextMessage = 0; asm("sti"); memcpy((char *)Msg, (char *)temp, sizeof(struct Message)); DeallocMem(temp); }
//============================================== // Open the file "path" and assign an FCB to it //============================================== struct FCB *OpenFile(char *path) { struct FCB *fcb = AllocKMem(sizeof(struct FCB)); fcb->inode = AllocKMem(sizeof(struct ext2_inode)); fcb->inodeNumber = GetFileINode(path); if (!fcb->inodeNumber) { DeallocMem(fcb); return (struct FCB *) -ENOENT; } GetINode(fcb->inodeNumber, fcb->inode); fcb->nextFCB = 0; fcb->fileCursor = 0; fcb->bufCursor = 0; fcb->buffer = AllocKMem((size_t)block_size); fcb->bufferIsDirty = 0; fcb->inodeIsDirty = 0; fcb->index1 = fcb->index2 = fcb->index3 = fcb->index4 = 0; fcb->currentBlock = fcb->inode->i_block[0]; ReadBlock(fcb->currentBlock, fcb->buffer); return fcb; }
BOOL PsGetModuleInfo(HANDLE ProcessHandle, BOOL IsProcessInitialized, BOOL IsModule32, LPCWSTR ModuleName, PMODULE_INFO ModuleInfo) { BOOL result; MODULE_INFO *modules; SIZE_T numOfModules; WCHAR compareModuleName[MAX_PATH]; WCHAR retModuleName[MAX_PATH]; result = wcscpy_s(compareModuleName, MAX_PATH, ModuleName) == 0; if (!result) { return FALSE; } result = _wcsupr_s(compareModuleName, MAX_PATH) == 0; if (!result) { return FALSE; } modules = (PMODULE_INFO)AllocMem(sizeof(MODULE_INFO) * 0x1000); if (!modules) { return FALSE; } result = PsGetProcessModules(ProcessHandle, IsProcessInitialized, modules, 0x1000, &numOfModules); if (!result) { DeallocMem(modules); return FALSE; } if (numOfModules == 0) { DeallocMem(modules); return FALSE; } for (SIZE_T i = 0; i < numOfModules; ++i) { if (IsModule32 && ((UINT64)(modules[i].ModuleHandle)) > 0xFFFFFFFFULL) { continue; } result = wcscpy_s(retModuleName, MAX_PATH, modules[i].ModuleName) == 0; if (!result) { DeallocMem(modules); return FALSE; } result = _wcsupr_s(retModuleName, MAX_PATH) == 0; if (!result) { DeallocMem(modules); return FALSE; } result = wcscmp(retModuleName, compareModuleName) == 0; if (result) { ModuleInfo->ModuleHandle = modules[i].ModuleHandle; wcscpy_s(ModuleInfo->ModuleName, MAX_PATH, modules[i].ModuleName); wcscpy_s(ModuleInfo->ModulePath, MAX_PATH, modules[i].ModulePath); DeallocMem(modules); return TRUE; } } DeallocMem(modules); return FALSE; }
BOOL PsGetModulesByProcessHandle(HANDLE ProcessHandle, MODULE_INFO *Entries, SIZE_T NumOfEntries, PSIZE_T RealNumOfEntries) { BOOL result; HMODULE *modules; DWORD needSize; SIZE_T moduleOffset = 0; SIZE_T moduleCounter = 0; if (!RealNumOfEntries) { return FALSE; } modules = (HMODULE*)AllocMem(sizeof(HMODULE) * NumOfEntries); if (!modules) { return FALSE; } result = EnumProcessModulesEx(ProcessHandle, modules, (DWORD)(sizeof(HMODULE) * NumOfEntries), &needSize, LIST_MODULES_ALL); if (!result) { DeallocMem(modules); return FALSE; } *RealNumOfEntries = needSize / sizeof(HMODULE); do { result = FALSE; moduleCounter++; if (moduleOffset >= NumOfEntries) { continue; } Entries[moduleOffset].ModuleHandle = modules[moduleOffset]; GetModuleFileNameEx(ProcessHandle, modules[moduleOffset], Entries[moduleOffset].ModulePath, MAX_PATH); GetShortFileName(Entries[moduleOffset].ModulePath, Entries[moduleOffset].ModuleName, MAX_PATH); result = moduleCounter < (*RealNumOfEntries); moduleOffset++; } while (result); DeallocMem(modules); *RealNumOfEntries = moduleCounter; if (moduleCounter > NumOfEntries) { return FALSE; } return TRUE; }
//============================= // The actual filesystem task //============================= void fsTaskCode(void) { struct Message *FSMsg; struct MessagePort *tempPort; int result; struct FCB *fcb; struct FileInfo info; FSPort = AllocMessagePort(); FSMsg = ALLOCMSG; kprintf(3, 0, "Starting Filesystem Task"); FSPort->waitingProc = (struct Task *) -1L; FSPort->msgQueue = 0; InitializeHD(); while (1) { fcb = 0; ReceiveMessage(FSPort, FSMsg); tempPort = FSMsg->tempPort; switch (FSMsg->byte) { case CREATEFILE: fcb = CreateFile((char *) FSMsg->quad1); if (fcb > 0) fcb->pid = FSMsg->pid; FSMsg->quad1 = (long) fcb; break; case OPENFILE: fcb = OpenFile((char *) FSMsg->quad1); if ((long) fcb > 0) fcb->pid = FSMsg->pid; FSMsg->quad1 = (long) fcb; break; case CLOSEFILE: (void)CloseFile((struct FCB *) FSMsg->quad1); DeallocMem((void *) FSMsg->quad1); break; case READFILE: FSMsg->quad1 = ReadFile((struct FCB *) FSMsg->quad1, (char *) FSMsg->quad2, FSMsg->quad3); break; case WRITEFILE: FSMsg->quad1 = WriteFile((struct FCB *) FSMsg->quad1, (char *) FSMsg->quad2, FSMsg->quad3); break; case DELETEFILE: FSMsg->quad1 = DeleteFile((char *) FSMsg->quad1); break; case TESTFILE: if (!strcmp((char *) FSMsg->quad1, "/")) result = 1; else { result = (long) GetFileINode((char *) FSMsg->quad1); if (result != -ENOENT) result = 1; } FSMsg->quad1 = result; break; case GETFILEINFO: fcb = (struct FCB *) FSMsg->quad1; info.inode = (long) fcb->inodeNumber; info.mode = (long) fcb->inode->i_mode; info.uid = (long) fcb->inode->i_uid; info.gid = (long) fcb->inode->i_gid; info.size = (long) fcb->inode->i_size; info.atime = (long) fcb->inode->i_atime; info.ctime = (long) fcb->inode->i_ctime; info.mtime = (long) fcb->inode->i_mtime; memcpy((char *) FSMsg->quad2, (char *) (&info), sizeof(struct FileInfo)); break; case CREATEDIR: FSMsg->quad1 = CreateDir((char *) FSMsg->quad1); break; case SEEK: FSMsg->quad1 = Seek((struct FCB *) FSMsg->quad1, FSMsg->quad2, FSMsg->quad3); break; case TRUNCATE: FSMsg->quad1 = Truncate((struct FCB*) FSMsg->quad1, (u_int32_t)(FSMsg->quad2)); break; default: break; } SendMessage(tempPort, FSMsg); } }
//==================================================== // Create a new file. entry for a file of type type // Returns an FCB on success or a negative error code //==================================================== struct FCB *CreateFileWithType(char *name, long type) { char *parentDirectory, *fileName, *dirBuffer; u_int32_t parentINodeNo, inodeNo, i; u_int16_t recLength, sizeOfEntry, sizeOfNewEntry; struct ext2_inode *inode; struct ext2_dir_entry_2 *entry, *newEntry; struct FCB *dirFcb, *fcb; // Does the file already exist? if (GetFileINode(name)) return (struct FCB *) -EEXIST; // Get the INode of the parentdirectory parentDirectory = AllocUMem((size_t)(strlen(name) + 1)); strcpy(parentDirectory, name); fileName = strrchr(parentDirectory, '/'); fileName[0] = 0; fileName++; parentINodeNo = GetFileINode(parentDirectory); if (!parentINodeNo) { DeallocMem(parentDirectory); return (struct FCB *) -ENOENT; } // Create an inode for the new file inode = AllocKMem(sizeof(struct ext2_inode)); memset(inode, 0, sizeof(struct ext2_inode)); inode->i_mode = (u_int16_t)(EXT2_S_IFREG | EXT2_S_IRUSR | EXT2_S_IWUSR | EXT2_S_IRGRP | EXT2_S_IWGRP | EXT2_S_IROTH | EXT2_S_IWOTH); inode->i_atime = inode->i_ctime = inode->i_mtime = (u_int32_t)unixtime; inode->i_dtime = 0; inode->i_links_count = 1; inode->i_blocks = 0; inodeNo = GetFreeINode(0); // Write the new inode to disk PutINode(inodeNo, inode); // Create a directory entry for the new file dirFcb = OpenFileByInodeNumber(parentINodeNo); dirBuffer = AllocUMem(dirFcb->inode->i_size); (void)ReadFile(dirFcb, dirBuffer, (long)(dirFcb->inode->i_size)); sizeOfNewEntry = (u_int16_t)(8 + strlen(fileName) + 4 - strlen(fileName) % 4); entry = (struct ext2_dir_entry_2 *) dirBuffer; sizeOfEntry = (u_int16_t)(8 + entry->name_len + 4 - entry->name_len % 4); while (sizeOfEntry + sizeOfNewEntry > entry->rec_len) { entry = (struct ext2_dir_entry_2 *) ((char *) entry + entry->rec_len); sizeOfEntry = (u_int16_t)(8 + entry->name_len + 4 - entry->name_len % 4); } // There's room for the new entry at the end of this record recLength = entry->rec_len; entry->rec_len = sizeOfEntry; newEntry = AllocUMem(sizeof(struct ext2_dir_entry_2)); memset(newEntry, 0, sizeof(struct ext2_dir_entry_2)); newEntry->file_type = (u_int8_t)type; newEntry->inode = (u_int32_t)inodeNo; newEntry->name_len = (u_int8_t)strlen(fileName); newEntry->rec_len = recLength - sizeOfEntry; for (i = 0; i < newEntry->name_len; i++) newEntry->name[i] = fileName[i]; memcpy((char *) entry + sizeOfEntry, newEntry, sizeOfNewEntry); DeallocMem(parentDirectory); // Write the directory buffer back to disk (void)Seek(dirFcb, 0, SEEK_SET); (void)WriteFile(dirFcb, dirBuffer, (long)(dirFcb->inode->i_size)); DeallocMem(dirBuffer); (void)CloseFile(dirFcb); // Create a FCB for the new file fcb = AllocKMem(sizeof(struct FCB)); fcb->inode = inode; fcb->inodeNumber = inodeNo; fcb->nextFCB = 0; fcb->fileCursor = 0; fcb->bufCursor = 0; fcb->buffer = AllocKMem((size_t)block_size); fcb->currentBlock = 0; fcb->index1 = fcb->index2 = fcb->index3 = fcb->index4 = 0; return fcb; }
//=============================================== // Delete the file name // Returns 0 on success or a negative error code //=============================================== long DeleteFile(char *name) { char *buffer = AllocKMem(block_size); char *buffer1 = AllocKMem(block_size); __le32 *blocks; __le32 *iblocks; int i, j; char *parentDirectory, *fileName, *dirBuffer; u_int32_t parentINodeNo; struct FCB *fcb, *dirFcb; struct ext2_dir_entry_2 *entry, *prevEntry; // Get the INode of the parentdirectory parentDirectory = AllocUMem((size_t)strlen(name) + 1); strcpy(parentDirectory, name); fileName = strrchr(parentDirectory, '/'); fileName[0] = 0; fileName++; parentINodeNo = GetFileINode(parentDirectory); if (parentINodeNo == (u_int32_t) -ENOENT) { DeallocMem(buffer); DeallocMem(buffer1); DeallocMem(parentDirectory); return -ENOENT; } // Now free the blocks allocated to this file fcb = OpenFile(name); if ((long)fcb < 0) { DeallocMem(buffer); DeallocMem(buffer1); DeallocMem(parentDirectory); return (long) fcb; } // Delete all direct blocks for (i = 0; i < EXT2_IND_BLOCK; i++) if (fcb->inode->i_block[i]) ClearBlockBitmapBit(fcb->inode->i_block[i]); if (fcb->inode->i_block[EXT2_IND_BLOCK]) { // Delete indirect blocks ReadBlock(fcb->inode->i_block[EXT2_IND_BLOCK], buffer); blocks = (__le32 *) buffer; for (i = 0; i < block_size / sizeof(__le32); i++) if (blocks[i]) ClearBlockBitmapBit(blocks[i]); ClearBlockBitmapBit(fcb->inode->i_block[EXT2_IND_BLOCK]); } if (fcb->inode->i_block[EXT2_DIND_BLOCK]) { // Delete double-indirect blocks ReadBlock(fcb->inode->i_block[EXT2_DIND_BLOCK], buffer); blocks = (__le32 *) buffer; for (i = 0; i < block_size / sizeof(__le32); i++) { if (blocks[i]) { ReadBlock(blocks[i], buffer1); iblocks = (__le32 *) buffer1; for (j = 0; j < block_size / sizeof(__le32); j++) if (iblocks[j]) ClearBlockBitmapBit(iblocks[j]); ClearBlockBitmapBit(blocks[i]); } } ClearBlockBitmapBit(fcb->inode->i_block[EXT2_DIND_BLOCK]); } if (fcb->inode->i_block[EXT2_TIND_BLOCK]) { // Delete triple-indirect blocks } // Find the directory entry for thefile dirFcb = OpenFileByInodeNumber(parentINodeNo); dirBuffer = AllocUMem(dirFcb->inode->i_size); (void)ReadFile(dirFcb, dirBuffer, (long)(dirFcb->inode->i_size)); entry = (struct ext2_dir_entry_2 *) dirBuffer; prevEntry = entry; while (strlen(fileName) != entry->name_len || strncmp(entry->name, fileName, entry->name_len)) { if ((long)entry + entry->name_len - (long)dirBuffer > (long)dirFcb->inode->i_size) { DeallocMem(dirBuffer); (void)CloseFile(dirFcb); DeallocMem(buffer); DeallocMem(buffer1); DeallocMem(parentDirectory); return -ENOENT; } prevEntry = entry; entry = (struct ext2_dir_entry_2 *) ((char *) entry + entry->rec_len); } // Entry now points to the directory entry for this file, prevEntry to the previous one prevEntry->rec_len += entry->rec_len; (void)Seek(dirFcb, 0, SEEK_SET); (void)WriteFile(dirFcb, dirBuffer, (long)dirFcb->inode->i_size); DeallocMem(dirBuffer); (void)CloseFile(dirFcb); DeallocMem(buffer); DeallocMem(buffer1); DeallocMem(parentDirectory); // Finally, delete the inode memset(fcb->inode, 0, sizeof(struct ext2_inode)); PutINode(fcb->inodeNumber, fcb->inode); ClearINodeBitmapBit(fcb->inodeNumber); (void)CloseFile(fcb); return 0; }
//=============================================================================== // This loads the program "name" into memory, if it exists. //=============================================================================== long DoExec(char *name, char *environment) { struct FCB *fHandle; long argv, argc; int retval = -ENOEXEC; struct Message *FSMsg = ALLOCMSG; char *kname = AllocKMem((size_t) strlen(name) + 6); // Enough space for "/bin" + name strcpy(kname, "/bin/"); strcat(kname, name); // Open file FSMsg->nextMessage = 0; FSMsg->byte = OPENFILE; FSMsg->quad1 = (long) kname; FSMsg->quad2 = (long) fHandle; SendReceiveMessage(FSPort, FSMsg); fHandle = (struct FCB *) FSMsg->quad1; if ((long) fHandle > 0) { char magic[5]; char executable = 0; (void) SeekFile(FSMsg, fHandle, 10, SEEK_SET); (void) ReadFromFile(fHandle, magic, 4); magic[4] = 0; if (!strcmp(magic, "IJ64")) { (void) SeekFile(FSMsg, fHandle, 0, SEEK_SET); LoadFlat(fHandle); executable = 1; } else { (void) SeekFile(FSMsg, fHandle, 0, SEEK_SET); (void) ReadFromFile(fHandle, magic, 4); if (magic[0] == 0x7F) { (void) SeekFile(FSMsg, fHandle, 0, SEEK_SET); LoadElf(FSMsg, fHandle); executable = 1; } } //Close file and deallocate memory for structures FSMsg->nextMessage = 0; FSMsg->byte = CLOSEFILE; FSMsg->quad1 = (long) fHandle; SendReceiveMessage(FSPort, FSMsg); DeallocMem(kname); DeallocMem(FSMsg); if (executable) { long *l; // Process the arguments for argc and argv // Copy environment string to user data space // It occupies the 81 bytes after the current first free memory currentTask->environment = (void *) currentTask->firstfreemem; memcpy(currentTask->environment, environment, 80); currentTask->firstfreemem += 80; argv = (long) currentTask->environment; argc = ParseEnvironmentString(&argv); argv += 80; // Adjust firstfreemem to point to the first free memory location. currentTask->firstfreemem += argc * sizeof(char *); // Build the first MemStruct struct. Is all this necessary? User tasks don't use the kernel memory allocation, do they? l = (long *) (currentTask->firstfreemem); *l = 0; *(l + 1) = -(long) (((sizeof(struct MemStruct) + currentTask->firstfreemem)) % PageSize); asm("mov %0,%%rdi;" "mov %1,%%rsi": : "r"(argc), "r"(argv):"%rax", "%rdi"); return 0; } else return retval;
BOOL PeReadExportTable(HANDLE ProcessHandle, BOOL AsX86, LPVOID ModuleBase, PDWORD NumOfFunctions, PDWORD NumOfNames, PDWORD NumOfOrdinals, DWORD **AddressTable, DWORD **NameTable, WORD **OrdinalTable) { BOOL result; IMAGE_NT_HEADERS32 ntHeader32; IMAGE_NT_HEADERS64 ntHeader64; IMAGE_EXPORT_DIRECTORY exportDirectory; DWORD exportDirectoryRVA; LPVOID exportDirectoryBase; LPVOID addressBase; LPVOID nameBase; LPVOID ordinalBase; if (!NumOfFunctions || !NumOfNames || !NumOfOrdinals) { return FALSE; } if (!AddressTable || !NameTable || !OrdinalTable) { return FALSE; } if (AsX86) { result = PeReadNtHeader32(ProcessHandle, ModuleBase, &ntHeader32); } else { result = PeReadNtHeader64(ProcessHandle, ModuleBase, &ntHeader64); } if (!result) { return FALSE; } if (AsX86) { exportDirectoryRVA = ntHeader32.OptionalHeader.DataDirectory[0].VirtualAddress; } else { exportDirectoryRVA = ntHeader64.OptionalHeader.DataDirectory[0].VirtualAddress; } exportDirectoryBase = (LPVOID)((uintptr_t)ModuleBase + exportDirectoryRVA); result = ReadProcessMemory(ProcessHandle, exportDirectoryBase, &exportDirectory, sizeof(exportDirectory), NULL); if (!result) { return FALSE; } *NumOfFunctions = exportDirectory.NumberOfFunctions; *NumOfNames = exportDirectory.NumberOfNames; *NumOfOrdinals = exportDirectory.NumberOfFunctions; *AddressTable = (DWORD*)AllocMem(sizeof(DWORD) * exportDirectory.NumberOfFunctions); if (!(*AddressTable)) { return FALSE; } *NameTable = (DWORD*)AllocMem(sizeof(DWORD) * exportDirectory.NumberOfNames); if (!(*NameTable)) { DeallocMem(*AddressTable); return FALSE; } *OrdinalTable = (WORD*)AllocMem(sizeof(WORD) * exportDirectory.NumberOfFunctions); if (!(*OrdinalTable)) { DeallocMem(*AddressTable); DeallocMem(*NameTable); return FALSE; } addressBase = (LPVOID)((uintptr_t)ModuleBase + exportDirectory.AddressOfFunctions); nameBase = (LPVOID)((uintptr_t)ModuleBase + exportDirectory.AddressOfNames); ordinalBase = (LPVOID)((uintptr_t)ModuleBase + exportDirectory.AddressOfNameOrdinals); result = ReadProcessMemory(ProcessHandle, addressBase, *AddressTable, sizeof(DWORD) * exportDirectory.NumberOfFunctions, NULL); if (!result) { DeallocMem(*AddressTable); DeallocMem(*NameTable); DeallocMem(*OrdinalTable); return FALSE; } result = ReadProcessMemory(ProcessHandle, nameBase, *NameTable, sizeof(DWORD) * exportDirectory.NumberOfNames, NULL); if (!result) { DeallocMem(*AddressTable); DeallocMem(*NameTable); DeallocMem(*OrdinalTable); return FALSE; } result = ReadProcessMemory(ProcessHandle, ordinalBase, *OrdinalTable, sizeof(WORD) * exportDirectory.NumberOfFunctions, NULL); if (!result) { DeallocMem(*AddressTable); DeallocMem(*NameTable); DeallocMem(*OrdinalTable); return FALSE; } return TRUE; }