Add an entry to the import table of PE - windows

I'm looking for a command line program to add an entry to the import table of a PE file.
My goal is to add a new imported function from an external DLL to my EXE, and then with ollydbg insert new code using code caves. The new code will use the newly imported function.
Acctualy I've achived my goal, but to add a new entry to the import table I used Stud_PE, which is a GUI application and I want to automate this part of the process.
I'd consider programmatically solutions, but I'm affraid the PE structure is too complex for me to learn and explore in the time frame I have. Moreover if an implementation is already exists, it would be a shame not to use it. :-)

Found what is was looking for.
m-PEFile for c++: http://forum.exetools.com/showpost.php?s=17e7516356489bb9dd17e294e147ef96&p=60183&postcount=3
Also check out pefile for python: http://code.google.com/p/pefile/
And PE/COFF 4J for java: http://pecoff4j.sourceforge.net/
PE/COFF 4J has limited functionality in my opinion, but maybe you'll find it helpful.
Code: PEFile.h
/*******************************************************************************
******************************** Team AT4RE ********************************
********************************************************************************
******************* PLEASE DON'T CHANGE/REMOVE THIS HEADER *******************
********************************************************************************
** **
** Title: PEFile class. **
** Desc: A handy class to manipulate pe files. **
** Author: MohammadHi [ in4matics at hotmail dot com ] **
** WwW: AT4RE [ http://www.at4re.com ] **
** Date: 2008-01-28 **
** **
********************************************************************************
*******************************************************************************/
/*
[ PE File Format ]
---------------------
| DOS Header |
---------------------
| DOS Stub |
---------------------
| PE Header |
---------------------
| Section Table |
---------------------
| Padding |
---------------------
| Section 1 |
---------------------
| Section 2 |
---------------------
| ... |
---------------------
| Section n |
---------------------*/
//==============================================================================
#pragma once
#pragma pack(1)
//==============================================================================
#include <windows.h>
//==============================================================================
#define MAX_SECTION_COUNT 64
#define SECTION_IMPORT "#.import"
#define SECTION_RESERV "#.reserv"
//==============================================================================
struct PE_DOS_HEADER {
WORD Signature;
WORD LastPageBytes;
WORD NumberOfPages;
WORD Relocations;
WORD HeaderSize;
WORD MinMemory;
WORD MaxMemory;
WORD InitialSS;
WORD InitialSP;
WORD Checksum;
WORD InitialIP;
WORD InitialCS;
WORD RelocTableOffset;
WORD Overlay;
WORD Reserved1[4];
WORD OemId;
WORD OemInfo;
WORD Reserved2[10];
LONG PEHeaderOffset;
};
struct PE_DOS_STUB {
char* RawData;
DWORD Size;
};
struct PE_SECTION_DATA {
DWORD Offset;
char* RawData;
DWORD Size;
};
struct PE_IMPORT_FUNCTION {
char* FunctionName;
int FunctionId;
PE_IMPORT_FUNCTION* Next;
};
struct PE_IMPORT_DLL {
char* DllName;
PE_IMPORT_FUNCTION* Functions;
PE_IMPORT_DLL* Next;
};
//==============================================================================
typedef IMAGE_NT_HEADERS PE_NT_HEADERS;
typedef IMAGE_SECTION_HEADER PE_SECTION_HEADER;
//==============================================================================
class PEFile {
public:
PE_DOS_HEADER dosHeader;
PE_DOS_STUB dosStub;
PE_NT_HEADERS peHeaders;
PE_SECTION_HEADER sectionTable[MAX_SECTION_COUNT];
PE_SECTION_DATA reservedData;
PE_SECTION_DATA sections[MAX_SECTION_COUNT];
PE_IMPORT_DLL importTable;
PE_IMPORT_DLL newImports;
PEFile();
PEFile(char* filePath);
~PEFile();
bool loadFromFile(char* filePath);
bool loadFromMemory(char* memoryAddress);
bool saveToFile(char* filePath);
int addSection(char* name, DWORD size, bool isExecutable);
void addImport(char* dllName, char** functions, int functionCount);
void commit();
private:
char* peMemory;
void init();
bool readFileData(char* filePath);
bool checkValidity();
bool readHeaders();
bool readBody();
bool readImportTable();
bool writePadding(HANDLE fileHandle, long paddingSize);
void unloadFile();
void buildImportTable();
char* buildNewImports(DWORD baseRVA);
DWORD calcNewImportsSize(DWORD &sizeDlls, DWORD &sizeFunctions, DWORD &sizeStrings);
DWORD alignNumber(DWORD number, DWORD alignment);
DWORD rvaToOffset(DWORD rva);
DWORD offsetToRVA(DWORD offset);
void fixReservedData();
void fixHeaders();
void fixSectionTable();
};
//==============================================================================
Code: PEFile.cpp
/*******************************************************************************
******************************** Team AT4RE ********************************
********************************************************************************
******************* PLEASE DON'T CHANGE/REMOVE THIS HEADER *******************
********************************************************************************
** **
** Title: PEFile class. **
** Desc: A handy class to manipulate pe files. **
** Author: MohammadHi [ in4matics at hotmail dot com ] **
** WwW: AT4RE [ http://www.at4re.com ] **
** Date: 2008-01-28 **
** **
********************************************************************************
*******************************************************************************/
#include "PEFile.h"
#include <math.h>
//==============================================================================
#define DEBUG_ENABLED true;
#ifdef DEBUG_ENABLED
#define echo(x) MessageBox(0, x, "DEBUG", MB_ICONERROR);
#define echo2(x, y) { char v[256]; strcpy_s(v, 256, x); strcat_s(v, 256, y); echo(v); }
#define echo3(x, y, z) { char w[256]; strcpy_s(w, 256, x); strcat_s(w, 256, y); echo2(w, z); }
#else
#define echo(x) ;
#define echo2(x, y) ;
#define echo3(x, y, z) ;
#endif
//==============================================================================
PEFile::PEFile() {
init();
}
//==============================================================================
PEFile::PEFile(char* filePath) {
init();
loadFromFile(filePath);
}
//==============================================================================
PEFile::~PEFile() {
unloadFile();
}
//==============================================================================
void PEFile::init() {
peMemory = NULL;
ZeroMemory(&newImports, sizeof(PE_IMPORT_DLL));
}
//==============================================================================
bool PEFile::readFileData(char* filePath) {
// open the file for read
HANDLE fileHandle = CreateFile(filePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (fileHandle == INVALID_HANDLE_VALUE) {
echo3("Couldn't open file : [", filePath, "]");
return false;
}
// get the file size
DWORD fileSize = GetFileSize(fileHandle, 0);
if (fileSize == 0) {
CloseHandle(fileHandle);
echo3("File size is ZeR0! : [", filePath, "]");
return false;
}
// allocate memory to read the pe file (note that we used VirtualAlloc not GlobalAlloc!)
peMemory = (char*)VirtualAlloc(NULL, fileSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if (peMemory == NULL) {
CloseHandle(fileHandle);
echo("Couldn't allocate memory!");
return false;
}
DWORD bytesRead;
// read whole file data
if (!ReadFile(fileHandle, peMemory, fileSize, &bytesRead, NULL) || bytesRead != fileSize) {
CloseHandle(fileHandle);
echo3("Couldn't read file! : [", filePath, "]");
return false;
}
// close the file
CloseHandle(fileHandle);
return true;
}
//==============================================================================
bool PEFile::checkValidity() {
// 'dosHeader.Signature' must be "MZ" && 'peHeaders.Signature' must be "PE\0\0"
if (dosHeader.Signature != IMAGE_DOS_SIGNATURE || peHeaders.Signature != IMAGE_NT_SIGNATURE) {
unloadFile();
echo("Invalid PE file!");
return false;
}
if (peHeaders.FileHeader.NumberOfSections > MAX_SECTION_COUNT) {
unloadFile();
echo("Number of sections > MAX_SECTION_COUNT !");
return false;
}
return true;
}
//==============================================================================
bool PEFile::readHeaders() {
// read dos/pe headers
CopyMemory(&dosHeader, peMemory, sizeof(PE_DOS_HEADER));
dosStub.RawData = peMemory + sizeof(PE_DOS_HEADER);
dosStub.Size = dosHeader.PEHeaderOffset - sizeof(PE_DOS_HEADER);
CopyMemory(&peHeaders, peMemory + dosHeader.PEHeaderOffset, sizeof(PE_NT_HEADERS));
// check validity of the file to ensure that we loaded a "PE File" not another thing!
if (!checkValidity()) {
return false;
}
// read section table
ZeroMemory(sectionTable, sizeof(sectionTable));
CopyMemory(sectionTable, peMemory + dosHeader.PEHeaderOffset + sizeof(PE_NT_HEADERS),
peHeaders.FileHeader.NumberOfSections * sizeof(PE_SECTION_HEADER));
return true;
}
//==============================================================================
bool PEFile::readBody() {
// read reserved data
DWORD reservedDataOffset = dosHeader.PEHeaderOffset + sizeof(PE_NT_HEADERS) +
peHeaders.FileHeader.NumberOfSections * sizeof(PE_SECTION_HEADER);
reservedData.Offset = reservedDataOffset;
reservedData.RawData = peMemory + reservedDataOffset;
/*reservedData.Size = peHeaders.OptionalHeader.SizeOfHeaders - reservedDataOffset;*/
if (sectionTable[0].PointerToRawData > 0) {
reservedData.Size = sectionTable[0].PointerToRawData - reservedDataOffset;
} else {
reservedData.Size = sectionTable[0].VirtualAddress - reservedDataOffset;
}
// read sections
for (int i = 0; i < peHeaders.FileHeader.NumberOfSections; i++) {
sections[i].Offset = sectionTable[i].PointerToRawData;
sections[i].RawData = peMemory + sectionTable[i].PointerToRawData;
sections[i].Size = sectionTable[i].SizeOfRawData;
}
return true;
}
//==============================================================================
bool PEFile::readImportTable() {
DWORD tableRVA = peHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
DWORD tableOffset = rvaToOffset(tableRVA);
if (tableOffset == 0) {
return false;
}
ZeroMemory(&importTable, sizeof(PE_IMPORT_DLL));
IMAGE_IMPORT_DESCRIPTOR* importDesc = (IMAGE_IMPORT_DESCRIPTOR*)(peMemory + tableOffset);
IMAGE_THUNK_DATA* importThunk;
PE_IMPORT_DLL* importDll = &this->importTable;
PE_IMPORT_FUNCTION* importFunction;
while (true) {
importDll->DllName = (char*)(peMemory + rvaToOffset(importDesc->Name));
if (importDesc->OriginalFirstThunk > 0) {
importThunk = (IMAGE_THUNK_DATA*)(peMemory + rvaToOffset(importDesc->OriginalFirstThunk));
} else {
importThunk = (IMAGE_THUNK_DATA*)(peMemory + rvaToOffset(importDesc->FirstThunk));
}
importDll->Functions = new PE_IMPORT_FUNCTION();
ZeroMemory(importDll->Functions, sizeof(PE_IMPORT_FUNCTION));
importFunction = importDll->Functions;
while (true) {
if ((importThunk->u1.Ordinal & IMAGE_ORDINAL_FLAG32) == IMAGE_ORDINAL_FLAG32) {
importFunction->FunctionId = IMAGE_ORDINAL32(importThunk->u1.Ordinal);
} else {
DWORD nameOffset = rvaToOffset(importThunk->u1.AddressOfData);
importFunction->FunctionName = (char*)(peMemory + nameOffset + 2);
}
importThunk = (IMAGE_THUNK_DATA*)((char*)importThunk + sizeof(IMAGE_THUNK_DATA));
if (importThunk->u1.AddressOfData == 0) {
break;
}
importFunction->Next = new PE_IMPORT_FUNCTION();
ZeroMemory(importFunction->Next, sizeof(PE_IMPORT_FUNCTION));
importFunction = importFunction->Next;
}
importDesc = (IMAGE_IMPORT_DESCRIPTOR*)((char*)importDesc + sizeof(IMAGE_IMPORT_DESCRIPTOR));
if (importDesc->Name == 0) {
break;
}
importDll->Next = new PE_IMPORT_DLL();
ZeroMemory(importDll->Next, sizeof(PE_IMPORT_DLL));
importDll = importDll->Next;
}
return true;
}
//==============================================================================
bool PEFile::loadFromFile(char* filePath) {
unloadFile();
return readFileData(filePath) &&
readHeaders() &&
readBody() &&
readImportTable();
}
//==============================================================================
bool PEFile::loadFromMemory(char* memoryAddress) {
unloadFile();
peMemory = memoryAddress;
return readHeaders()/* &&
readBody() &&
readImportTable()*/;
}
//==============================================================================
bool PEFile::saveToFile(char* filePath) {
commit();
buildImportTable();
// create the output file
HANDLE fileHandle = CreateFile(filePath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (fileHandle == INVALID_HANDLE_VALUE) {
echo("Couldn't create file");
return false;
}
DWORD bytesWritten;
WriteFile(fileHandle, &dosHeader, sizeof(PE_DOS_HEADER), &bytesWritten, NULL);
WriteFile(fileHandle, dosStub.RawData, dosStub.Size, &bytesWritten, NULL);
writePadding(fileHandle, dosHeader.PEHeaderOffset - sizeof(PE_DOS_HEADER) - dosStub.Size);
WriteFile(fileHandle, &peHeaders, sizeof(PE_NT_HEADERS), &bytesWritten, NULL);
WriteFile(fileHandle, &sectionTable, peHeaders.FileHeader.NumberOfSections * sizeof(PE_SECTION_HEADER), &bytesWritten, NULL);
WriteFile(fileHandle, reservedData.RawData, reservedData.Size, &bytesWritten, NULL);
for (int i = 0; i < peHeaders.FileHeader.NumberOfSections; i++) {
writePadding(fileHandle, sectionTable[i].PointerToRawData - GetFileSize(fileHandle, NULL));
WriteFile(fileHandle, sections[i].RawData, sections[i].Size, &bytesWritten, NULL);
}
CloseHandle(fileHandle);
return true;
}
//==============================================================================
bool PEFile::writePadding(HANDLE fileHandle, long paddingSize) {
if (paddingSize <= 0)
return false;
DWORD bytesWritten;
char* padding = new char[paddingSize];
memset(padding, 0, paddingSize);
WriteFile(fileHandle, padding, paddingSize, &bytesWritten, NULL);
delete padding;
return (bytesWritten == paddingSize);
}
//==============================================================================
void PEFile::unloadFile() {
if (peMemory != NULL) {
VirtualFree(peMemory, 0, MEM_RELEASE);
peMemory = NULL;
}
}
//==============================================================================
void PEFile::buildImportTable() {
DWORD sizeDlls = 0;
DWORD sizeFunctions = 0;
DWORD sizeStrings = 0;
DWORD newImportsSize = calcNewImportsSize(sizeDlls, sizeFunctions, sizeStrings);
// we'll move the old dll list to the new import table, so we'll calc its size
DWORD oldImportDllsSize = 0;
PE_IMPORT_DLL* importDll = &this->importTable;
while (importDll != NULL) {
oldImportDllsSize += sizeof(IMAGE_IMPORT_DESCRIPTOR);
importDll = importDll->Next;
}
// add a new section to handle the new import table
int index = addSection(SECTION_IMPORT, oldImportDllsSize + newImportsSize, false);
// copy old import dll list
DWORD oldImportTableRVA = peHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
DWORD oldImportTableOffset = rvaToOffset(oldImportTableRVA);
CopyMemory(sections[index].RawData, peMemory + oldImportTableOffset, oldImportDllsSize);
// copy new imports
char* newImportsData = buildNewImports(sectionTable[index].VirtualAddress + oldImportDllsSize);
CopyMemory(sections[index].RawData + oldImportDllsSize, newImportsData, newImportsSize);
peHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress = sectionTable[index].VirtualAddress;
peHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size = sectionTable[index].SizeOfRawData;
peHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress = 0;
peHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].Size = 0;
}
//==============================================================================
char* PEFile::buildNewImports(DWORD baseRVA) {
commit();
IMAGE_IMPORT_DESCRIPTOR importDesc;
IMAGE_THUNK_DATA importThunk;
PE_IMPORT_DLL* importDll;
PE_IMPORT_FUNCTION* importFunction;
DWORD sizeDlls = 0;
DWORD sizeFunctions = 0;
DWORD sizeStrings = 0;
DWORD newImportsSize = calcNewImportsSize(sizeDlls, sizeFunctions, sizeStrings);
DWORD offsetDlls = 0;
DWORD offsetFunctions = sizeDlls;
DWORD offsetStrings = sizeDlls + 2 * sizeFunctions;
char* buffer = new char[newImportsSize];
ZeroMemory(buffer, newImportsSize);
importDll = &newImports;
while (importDll != NULL) {
ZeroMemory(&importDesc, sizeof(IMAGE_IMPORT_DESCRIPTOR));
importDesc.OriginalFirstThunk = baseRVA + offsetFunctions;
importDesc.FirstThunk = baseRVA + offsetFunctions + sizeFunctions;
importDesc.Name = baseRVA + offsetStrings;
CopyMemory(buffer + offsetStrings, importDll->DllName, strlen(importDll->DllName));
offsetStrings += alignNumber((DWORD)strlen(importDll->DllName) + 1, 2);
CopyMemory(buffer + offsetDlls, &importDesc, sizeof(IMAGE_IMPORT_DESCRIPTOR));
offsetDlls += sizeof(IMAGE_IMPORT_DESCRIPTOR);
importFunction = importDll->Functions;
while (importFunction != NULL) {
ZeroMemory(&importThunk, sizeof(IMAGE_THUNK_DATA));
if (importFunction->FunctionId != 0) {
importThunk.u1.Ordinal = importFunction->FunctionId | IMAGE_ORDINAL_FLAG32;
} else {
importThunk.u1.AddressOfData = baseRVA + offsetStrings;
CopyMemory(buffer + offsetStrings + 2, importFunction->FunctionName, strlen(importFunction->FunctionName));
offsetStrings += 2 + alignNumber((DWORD)strlen(importFunction->FunctionName) + 1, 2);
}
CopyMemory(buffer + offsetFunctions, &importThunk, sizeof(IMAGE_THUNK_DATA));
CopyMemory(buffer + offsetFunctions + sizeFunctions, &importThunk, sizeof(IMAGE_THUNK_DATA));
offsetFunctions += sizeof(IMAGE_THUNK_DATA);
importFunction = importFunction->Next;
}
offsetFunctions += sizeof(IMAGE_THUNK_DATA);
importDll = importDll->Next;
}
return buffer;
}
//==============================================================================
DWORD PEFile::calcNewImportsSize(DWORD &sizeDlls, DWORD &sizeFunctions, DWORD &sizeStrings) {
PE_IMPORT_DLL* importDll = &this->newImports;
PE_IMPORT_FUNCTION* importFunction;
// calc added imports size
while (importDll != NULL) {
sizeDlls += sizeof(IMAGE_IMPORT_DESCRIPTOR);
sizeStrings += alignNumber((DWORD)strlen(importDll->DllName) + 1, 2);
importFunction = importDll->Functions;
while (importFunction != NULL) {
sizeFunctions += sizeof(IMAGE_THUNK_DATA);
if (importFunction->FunctionId == 0) {
sizeStrings += 2 + alignNumber((DWORD)strlen(importFunction->FunctionName) + 1, 2);
}
importFunction = importFunction->Next;
}
sizeFunctions += sizeof(IMAGE_THUNK_DATA); // for the terminator thunk data
importDll = importDll->Next;
}
sizeDlls += sizeof(IMAGE_IMPORT_DESCRIPTOR); // for the terminator import descriptor
return sizeDlls + 2 * sizeFunctions + sizeStrings;
}
//==============================================================================
int PEFile::addSection(char* name, DWORD size, bool isExecutable) {
if (peHeaders.FileHeader.NumberOfSections == MAX_SECTION_COUNT) {
return -1;
}
PE_SECTION_DATA &newSection = sections[peHeaders.FileHeader.NumberOfSections];
PE_SECTION_HEADER &newSectionHeader = sectionTable[peHeaders.FileHeader.NumberOfSections];
PE_SECTION_HEADER &lastSectionHeader = sectionTable[peHeaders.FileHeader.NumberOfSections - 1];
DWORD sectionSize = alignNumber(size, peHeaders.OptionalHeader.FileAlignment);
DWORD virtualSize = alignNumber(sectionSize, peHeaders.OptionalHeader.SectionAlignment);
DWORD sectionOffset = alignNumber(lastSectionHeader.PointerToRawData + lastSectionHeader.SizeOfRawData, peHeaders.OptionalHeader.FileAlignment);
DWORD virtualOffset = alignNumber(lastSectionHeader.VirtualAddress + lastSectionHeader.Misc.VirtualSize, peHeaders.OptionalHeader.SectionAlignment);
ZeroMemory(&newSectionHeader, sizeof(IMAGE_SECTION_HEADER));
CopyMemory(newSectionHeader.Name, name, (strlen(name) > 8 ? 8 : strlen(name)));
newSectionHeader.PointerToRawData = sectionOffset;
newSectionHeader.VirtualAddress = virtualOffset;
newSectionHeader.SizeOfRawData = sectionSize;
newSectionHeader.Misc.VirtualSize = virtualSize;
newSectionHeader.Characteristics = //0xC0000040;
IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_CNT_INITIALIZED_DATA;
if (isExecutable) {
newSectionHeader.Characteristics |= IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE;
}
newSection.RawData = (char*)GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT, sectionSize);
newSection.Size = sectionSize;
peHeaders.FileHeader.NumberOfSections++;
if (reservedData.Size > 0) {
reservedData.Size -= sizeof(IMAGE_SECTION_HEADER);
}
// return new section index
return peHeaders.FileHeader.NumberOfSections - 1;
}
//==============================================================================
void PEFile::addImport(char* dllName, char** functions, int functionCount) {
PE_IMPORT_DLL* importDll = &this->newImports;
PE_IMPORT_FUNCTION* importFunction;
if (newImports.DllName != NULL) {
while (importDll->Next != NULL) {
importDll = importDll->Next;
}
importDll->Next = new PE_IMPORT_DLL();
importDll = importDll->Next;
}
importDll->DllName = dllName;
importDll->Functions = new PE_IMPORT_FUNCTION();
importDll->Next = NULL;
importFunction = importDll->Functions;
importFunction->FunctionName = functions[0];
for (int i = 1; i < functionCount; i++) {
importFunction->Next = new PE_IMPORT_FUNCTION();
importFunction = importFunction->Next;
importFunction->FunctionName = functions[i];
}
importFunction->Next = NULL;
}
//==============================================================================
DWORD PEFile::alignNumber(DWORD number, DWORD alignment) {
return (DWORD)(ceil(number / (alignment + 0.0)) * alignment);
}
//==============================================================================
DWORD PEFile::rvaToOffset(DWORD rva) {
for (int i = 0; i < peHeaders.FileHeader.NumberOfSections; i++) {
if (rva >= sectionTable[i].VirtualAddress &&
rva < sectionTable[i].VirtualAddress + sectionTable[i].Misc.VirtualSize) {
return sectionTable[i].PointerToRawData + (rva - sectionTable[i].VirtualAddress);
}
}
return 0;
}
//==============================================================================
DWORD PEFile::offsetToRVA(DWORD offset) {
for (int i = 0; i < peHeaders.FileHeader.NumberOfSections; i++) {
if (offset >= sectionTable[i].PointerToRawData &&
offset < sectionTable[i].PointerToRawData + sectionTable[i].SizeOfRawData) {
return sectionTable[i].VirtualAddress + (offset - sectionTable[i].PointerToRawData);
}
}
return 0;
}
//==============================================================================
void PEFile::commit() {
fixReservedData();
fixHeaders();
fixSectionTable();
}
//==============================================================================
void PEFile::fixReservedData() {
DWORD dirIndex = 0;
for (dirIndex = 0; dirIndex < peHeaders.OptionalHeader.NumberOfRvaAndSizes; dirIndex++) {
if (peHeaders.OptionalHeader.DataDirectory[dirIndex].VirtualAddress > 0 &&
peHeaders.OptionalHeader.DataDirectory[dirIndex].VirtualAddress >= reservedData.Offset &&
peHeaders.OptionalHeader.DataDirectory[dirIndex].VirtualAddress < reservedData.Size) {
break;
}
}
if (dirIndex == peHeaders.OptionalHeader.NumberOfRvaAndSizes) {
return;
}
int sectionIndex = addSection(SECTION_RESERV, reservedData.Size, false);
CopyMemory(sections[sectionIndex].RawData, reservedData.RawData, reservedData.Size);
for (dirIndex = 0; dirIndex < peHeaders.OptionalHeader.NumberOfRvaAndSizes; dirIndex++) {
if (peHeaders.OptionalHeader.DataDirectory[dirIndex].VirtualAddress > 0 &&
peHeaders.OptionalHeader.DataDirectory[dirIndex].VirtualAddress >= reservedData.Offset &&
peHeaders.OptionalHeader.DataDirectory[dirIndex].VirtualAddress < reservedData.Size) {
peHeaders.OptionalHeader.DataDirectory[dirIndex].VirtualAddress +=
sectionTable[sectionIndex].VirtualAddress - reservedData.Offset;
}
}
reservedData.Size = 0;
}
//==============================================================================
void PEFile::fixHeaders() {
peHeaders.OptionalHeader.SizeOfHeaders = alignNumber(dosHeader.PEHeaderOffset + peHeaders.FileHeader.SizeOfOptionalHeader +
peHeaders.FileHeader.NumberOfSections * sizeof(PE_SECTION_HEADER), peHeaders.OptionalHeader.FileAlignment);
DWORD imageSize = peHeaders.OptionalHeader.SizeOfHeaders;
for (int i = 0; i < peHeaders.FileHeader.NumberOfSections; i++) {
imageSize += alignNumber(sectionTable[i].Misc.VirtualSize, peHeaders.OptionalHeader.SectionAlignment);
}
peHeaders.OptionalHeader.SizeOfImage = alignNumber(imageSize, peHeaders.OptionalHeader.SectionAlignment);
peHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].VirtualAddress = 0;
peHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].Size = 0;
}
//==============================================================================
void PEFile::fixSectionTable() {
DWORD offset = peHeaders.OptionalHeader.SizeOfHeaders;
for (int i = 0; i < peHeaders.FileHeader.NumberOfSections; i++) {
sectionTable[i].Characteristics |= IMAGE_SCN_MEM_WRITE;
offset = alignNumber(offset, peHeaders.OptionalHeader.FileAlignment);
sectionTable[i].PointerToRawData = offset;
//sectionTable[i].SizeOfRawData = alignNumber(offset + sectionTable[i].Misc.VirtualSize, peHeaders.OptionalHeader.FileAlignment);
offset += sectionTable[i].SizeOfRawData;
}
}
//==============================================================================
#include "PEFile.h"
int main(int argc, char* argv[]) {
// Open the input file
PEFile pe("1.exe");
// Add "MessageBoxA" & "ShowWindow" functions to the import table
char* functions[] = { "MessageBoxA", "ShowWindow" };
pe.addImport("user32.dll", functions, 2);
// Add a new section named ".at4re" with size "0x1000" byte
pe.addSection(".at4re", 0x1000, false);
// Save the modified file
pe.saveToFile("1+.exe");
}

You can use the PeNet library to add a new import with just one line of code. For an example see here: Adding Imports
var peFile = new PeFile("myapp.exe");
peFile.AddImport("gdi32.dll", "StartPage");

I was looking for such program myself. I failed too.
But it is very easily done by hand.
If you need to automate it then you can make your own program.
Go to http://www.unknowncheats.me/forum/ or http://www.rohitab.com
People there will be able to help you write your own program.

Related

How to get windows folder display order by C + +

I need to get the pictures in the windows folder and sort them according to the order in which they are displayed. Now there is a method to traverse the entire folder display items through the handle by getting the folder window handle. However, this method has a drawback: it can't get the order of the unopened folder, because there is no open file and no window handle.
Qt is used.
Please forgive my grammatical mistakes.
//Find out the current folder window according to the mouse click position
HWND findOpenFileWindow(const QString& path)
{
Sleep(3 * 1000);
POINT pNow = { 0, 0 };
if (!GetCursorPos(&pNow))
return NULL;
TCHAR szClass[255] = {0};
HWND pMouseChooseHandle = WindowFromPoint(pNow);
HWND pParent = ::GetParent(pMouseChooseHandle);
GetClassName(pParent, szClass, 255);
if (_tcscmp(szClass, L"SHELLDLL_DefView") == 0 || _tcscmp(szClass, L"NSEViewClass") == 0 )
{
bool bQingDisk = _tcscmp(szClass, L"NSEViewClass") == 0;
pParent = ::GetParent(pParent);
GetClassName(pParent, szClass, 255);
if (_tcscmp(szClass, L"WorkerW"))
{
pParent = pMouseChooseHandle;
for (int i = 0; i < 6; i++)
{
if(pParent != NULL)
pParent = ::GetParent(pParent);
}
HWND pChild = ::GetWindow(pParent, GW_CHILD);
GetClassName(pChild, szClass, 255);
while (pChild != NULL)
{
GetClassName(pChild, szClass, 255);
if (_tcscmp(szClass, TEXT("ShellTabWindowClass")) == 0)
{
pParent = pChild;
break;
}
pChild = ::GetNextWindow(pChild, GW_HWNDNEXT);
}
TCHAR exploreWndName[MAX_PATH] = {0};
::GetWindowText(pParent, exploreWndName, MAX_PATH);
if(QFileInfo(path).fileName() == QString().fromWCharArray(exploreWndName))
return pParent;
}
}
return NULL;
}
//Traverse window display items, get them
QStringList listNormalFolderFile( const QString& path, const QStringList& filter )
{
HWND folderWnd = findOpenFileWindow(path);
HWND hwnd;
IDispatch *pDispatch;
CComPtr<IShellWindows> pShellWindows;
CoInitialize(NULL);
HRESULT hr = CoCreateInstance(CLSID_ShellWindows, NULL, CLSCTX_ALL, IID_PPV_ARGS(&pShellWindows));
if (FAILED(hr))
{
CoUninitialize();
return QStringList();
}
LONG lCount = 0;
pShellWindows->get_Count(&lCount);
QStringList fileList;
for (LONG i = 0; i < lCount; i++)
{
CComPtr<IShellBrowser> pShellBrowser;
VARIANT var;
var.vt = VT_I4;
var.lVal = i;
if(SUCCEEDED(pShellWindows->Item(var, &pDispatch)))
{
if(SUCCEEDED(IUnknown_QueryService(pDispatch, SID_STopLevelBrowser, IID_PPV_ARGS(&pShellBrowser))))
{
if (SUCCEEDED(IUnknown_GetWindow(pShellBrowser, &hwnd)))
{
TCHAR szBuf[256];
GetWindowText(hwnd, szBuf, sizeof(szBuf) / sizeof(TCHAR));
if(QFileInfo(path).fileName() != QString().fromWCharArray(szBuf))
continue;
CComPtr<IShellView> pShellView;
if(FAILED(pShellBrowser->QueryActiveShellView(&pShellView)))
continue;
CComPtr<IFolderView> pFv = NULL;
/*
do something here
*/
CComPtr<IPersistFolder2 > pFolder;
if( FAILED(pFv->GetFolder(IID_IPersistFolder2, (void**) &pFolder)))
continue;
LPITEMIDLIST pidl = nullptr;
if( SUCCEEDED(pFolder->GetCurFolder(&pidl)))
{
wchar_t cPath[32767];
if( ::SHGetPathFromIDList(pidl, cPath))
{
QString filePath;
QFileInfo fileInfo(filePath.fromWCharArray(cPath));
if(fileInfo.absoluteFilePath() == QFileInfo(path).absoluteFilePath())
{
if(folderWnd == NULL || folderWnd == hwnd)
{
fileList = listFileInBrowser(pShellBrowser, filter);
break;
}
}
}
}
}
}
}
}
CoUninitialize();
return fileList;

need Help in windivert webfilter

Hello every one i m trying to develop web filter and i found Win Divert Samples
here the code is i m trying to run in visual Studio 12 and got this error
IntelliSense: argument of type "PVOID" is incompatible with parameter of type "char *"
#include <winsock2.h>
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include "windivert.h"
#define MAXBUF 0xFFFF
#define MAXURL 4096
/*
* URL and blacklist representation.
*/
typedef struct
{
char *domain;
char *uri;
} URL, *PURL;
typedef struct
{
UINT size;
UINT length;
PURL *urls;
} BLACKLIST, *PBLACKLIST;
/*
* Pre-fabricated packets.
*/
typedef struct
{
WINDIVERT_IPHDR ip;
WINDIVERT_TCPHDR tcp;
} PACKET, *PPACKET;
typedef struct
{
PACKET header;
UINT8 data[];
} DATAPACKET, *PDATAPACKET;
/*
* THe block page contents.
*/
const char block_data[] =
"HTTP/1.1 200 OK\r\n"
"Connection: close\r\n"
"Content-Type: text/html\r\n"
"\r\n"
"<!doctype html>\n"
"<html>\n"
"\t<head>\n"
"\t\t<title>BLOCKED!</title>\n"
"\t</head>\n"
"\t<body>\n"
"\t\t<h1>BLOCKED!</h1>\n"
"\t\t<hr>\n"
"\t\t<p>This URL has been blocked!</p>\n"
"\t</body>\n"
"</html>\n";
/*
* Prototypes
*/
static void PacketInit(PPACKET packet);
static int __cdecl UrlCompare(const void *a, const void *b);
static int UrlMatch(PURL urla, PURL urlb);
static PBLACKLIST BlackListInit(void);
static void BlackListInsert(PBLACKLIST blacklist, PURL url);
static void BlackListSort(PBLACKLIST blacklist);
static BOOL BlackListMatch(PBLACKLIST blacklist, PURL url);
static void BlackListRead(PBLACKLIST blacklist, const char *filename);
static BOOL BlackListPayloadMatch(PBLACKLIST blacklist, char *data,
UINT16 len);
/*
* Entry.
*/
int __cdecl main(int argc, char **argv)
{
HANDLE handle;
WINDIVERT_ADDRESS addr;
UINT8 packet[MAXBUF];
UINT packet_len;
PWINDIVERT_IPHDR ip_header;
PWINDIVERT_TCPHDR tcp_header;
PVOID payload;
UINT payload_len;
PACKET reset0;
PPACKET reset = &reset0;
PACKET finish0;
PPACKET finish = &finish0;
PDATAPACKET blockpage;
UINT16 blockpage_len;
PBLACKLIST blacklist;
unsigned i;
INT16 priority = 404; // Arbitrary.
// Read the blacklists.
if (argc <= 1)
{
fprintf(stderr, "usage: %s blacklist.txt [blacklist2.txt ...]\n",
argv[0]);
exit(EXIT_FAILURE);
}
blacklist = BlackListInit();
for (i = 1; i < (UINT)argc; i++)
{
BlackListRead(blacklist, argv[i]);
}
BlackListSort(blacklist);
// Initialize the pre-frabricated packets:
blockpage_len = sizeof(DATAPACKET)+sizeof(block_data)-1;
blockpage = (PDATAPACKET)malloc(blockpage_len);
if (blockpage == NULL)
{
fprintf(stderr, "error: memory allocation failed\n");
exit(EXIT_FAILURE);
}
PacketInit(&blockpage->header);
blockpage->header.ip.Length = htons(blockpage_len);
blockpage->header.tcp.SrcPort = htons(80);
blockpage->header.tcp.Psh = 1;
blockpage->header.tcp.Ack = 1;
memcpy(blockpage->data, block_data, sizeof(block_data)-1);
PacketInit(reset);
reset->tcp.Rst = 1;
reset->tcp.Ack = 1;
PacketInit(finish);
finish->tcp.Fin = 1;
finish->tcp.Ack = 1;
// Open the Divert device:
handle = WinDivertOpen(
"outbound && " // Outbound traffic only
"ip && " // Only IPv4 supported
"tcp.DstPort == 80 && " // HTTP (port 80) only
"tcp.PayloadLength > 0", // TCP data packets only
WINDIVERT_LAYER_NETWORK, priority, 0
);
if (handle == INVALID_HANDLE_VALUE)
{
fprintf(stderr, "error: failed to open the WinDivert device (%d)\n",
GetLastError());
exit(EXIT_FAILURE);
}
printf("OPENED WinDivert\n");
// Main loop:
while (TRUE)
{
if (!WinDivertRecv(handle, packet, sizeof(packet), &addr, &packet_len))
{
fprintf(stderr, "warning: failed to read packet (%d)\n",
GetLastError());
continue;
}
if (!WinDivertHelperParsePacket(packet, packet_len, &ip_header, NULL,
NULL, NULL, &tcp_header, NULL, &payload, &payload_len) ||
!BlackListPayloadMatch(blacklist, payload, (UINT16)payload_len))
{
// Packet does not match the blacklist; simply reinject it.
if (!WinDivertSend(handle, packet, packet_len, &addr, NULL))
{
fprintf(stderr, "warning: failed to reinject packet (%d)\n",
GetLastError());
}
continue;
}
// The URL matched the blacklist; we block it by hijacking the TCP
// connection.
// (1) Send a TCP RST to the server; immediately closing the
// connection at the server's end.
reset->ip.SrcAddr = ip_header->SrcAddr;
reset->ip.DstAddr = ip_header->DstAddr;
reset->tcp.SrcPort = tcp_header->SrcPort;
reset->tcp.DstPort = htons(80);
reset->tcp.SeqNum = tcp_header->SeqNum;
reset->tcp.AckNum = tcp_header->AckNum;
WinDivertHelperCalcChecksums((PVOID)reset, sizeof(PACKET), 0);
if (!WinDivertSend(handle, (PVOID)reset, sizeof(PACKET), &addr, NULL))
{
fprintf(stderr, "warning: failed to send reset packet (%d)\n",
GetLastError());
}
// (2) Send the blockpage to the browser:
blockpage->header.ip.SrcAddr = ip_header->DstAddr;
blockpage->header.ip.DstAddr = ip_header->SrcAddr;
blockpage->header.tcp.DstPort = tcp_header->SrcPort;
blockpage->header.tcp.SeqNum = tcp_header->AckNum;
blockpage->header.tcp.AckNum =
htonl(ntohl(tcp_header->SeqNum) + payload_len);
WinDivertHelperCalcChecksums((PVOID)blockpage, blockpage_len, 0);
addr.Direction = !addr.Direction; // Reverse direction.
if (!WinDivertSend(handle, (PVOID)blockpage, blockpage_len, &addr,
NULL))
{
fprintf(stderr, "warning: failed to send block page packet (%d)\n",
GetLastError());
}
// (3) Send a TCP FIN to the browser; closing the connection at the
// browser's end.
finish->ip.SrcAddr = ip_header->DstAddr;
finish->ip.DstAddr = ip_header->SrcAddr;
finish->tcp.SrcPort = htons(80);
finish->tcp.DstPort = tcp_header->SrcPort;
finish->tcp.SeqNum =
htonl(ntohl(tcp_header->AckNum) + sizeof(block_data) - 1);
finish->tcp.AckNum =
htonl(ntohl(tcp_header->SeqNum) + payload_len);
WinDivertHelperCalcChecksums((PVOID)finish, sizeof(PACKET), 0);
if (!WinDivertSend(handle, (PVOID)finish, sizeof(PACKET), &addr, NULL))
{
fprintf(stderr, "warning: failed to send finish packet (%d)\n",
GetLastError());
}
}
}
/*
* Initialize a PACKET.
*/
static void PacketInit(PPACKET packet)
{
memset(packet, 0, sizeof(PACKET));
packet->ip.Version = 4;
packet->ip.HdrLength = sizeof(WINDIVERT_IPHDR) / sizeof(UINT32);
packet->ip.Length = htons(sizeof(PACKET));
packet->ip.TTL = 64;
packet->ip.Protocol = IPPROTO_TCP;
packet->tcp.HdrLength = sizeof(WINDIVERT_TCPHDR) / sizeof(UINT32);
}
/*
* Initialize an empty blacklist.
*/
static PBLACKLIST BlackListInit(void)
{
PBLACKLIST blacklist = (PBLACKLIST)malloc(sizeof(BLACKLIST));
UINT size;
if (blacklist == NULL)
{
goto memory_error;
}
size = 1024;
blacklist->urls = (PURL *)malloc(size*sizeof(PURL));
if (blacklist->urls == NULL)
{
goto memory_error;
}
blacklist->size = size;
blacklist->length = 0;
return blacklist;
memory_error:
fprintf(stderr, "error: failed to allocate memory\n");
exit(EXIT_FAILURE);
}
/*
* Insert a URL into a blacklist.
*/
static void BlackListInsert(PBLACKLIST blacklist, PURL url)
{
if (blacklist->length >= blacklist->size)
{
blacklist->size = (blacklist->size*3) / 2;
printf("GROW blacklist to %u\n", blacklist->size);
blacklist->urls = (PURL *)realloc(blacklist->urls,
blacklist->size*sizeof(PURL));
if (blacklist->urls == NULL)
{
fprintf(stderr, "error: failed to reallocate memory\n");
exit(EXIT_FAILURE);
}
}
blacklist->urls[blacklist->length++] = url;
}
/*
* Sort the blacklist (for searching).
*/
static void BlackListSort(PBLACKLIST blacklist)
{
qsort(blacklist->urls, blacklist->length, sizeof(PURL), UrlCompare);
}
/*
* Match a URL against the blacklist.
*/
static BOOL BlackListMatch(PBLACKLIST blacklist, PURL url)
{
int lo = 0, hi = ((int)blacklist->length)-1;
while (lo <= hi)
{
INT mid = (lo + hi) / 2;
int cmp = UrlMatch(url, blacklist->urls[mid]);
if (cmp > 0)
{
hi = mid-1;
}
else if (cmp < 0)
{
lo = mid+1;
}
else
{
return TRUE;
}
}
return FALSE;
}
/*
* Read URLs from a file.
*/
static void BlackListRead(PBLACKLIST blacklist, const char *filename)
{
char domain[MAXURL+1];
char uri[MAXURL+1];
int c;
UINT16 i, j;
PURL url;
FILE *file = fopen(filename, "r");
if (file == NULL)
{
fprintf(stderr, "error: could not open blacklist file %s\n",
filename);
exit(EXIT_FAILURE);
}
// Read URLs from the file and add them to the blacklist:
while (TRUE)
{
while (isspace(c = getc(file)))
;
if (c == EOF)
{
break;
}
if (c != '-' && !isalnum(c))
{
while (!isspace(c = getc(file)) && c != EOF)
;
if (c == EOF)
{
break;
}
continue;
}
i = 0;
domain[i++] = (char)c;
while ((isalnum(c = getc(file)) || c == '-' || c == '.') && i < MAXURL)
{
domain[i++] = (char)c;
}
domain[i] = '\0';
j = 0;
if (c == '/')
{
while (!isspace(c = getc(file)) && c != EOF && j < MAXURL)
{
uri[j++] = (char)c;
}
uri[j] = '\0';
}
else if (isspace(c))
{
uri[j] = '\0';
}
else
{
while (!isspace(c = getc(file)) && c != EOF)
;
continue;
}
printf("ADD %s/%s\n", domain, uri);
url = (PURL)malloc(sizeof(URL));
if (url == NULL)
{
goto memory_error;
}
url->domain = (char *)malloc((i+1)*sizeof(char));
url->uri = (char *)malloc((j+1)*sizeof(char));
if (url->domain == NULL || url->uri == NULL)
{
goto memory_error;
}
strcpy(url->uri, uri);
for (j = 0; j < i; j++)
{
url->domain[j] = domain[i-j-1];
}
url->domain[j] = '\0';
BlackListInsert(blacklist, url);
}
fclose(file);
return;
memory_error:
fprintf(stderr, "error: memory allocation failed\n");
exit(EXIT_FAILURE);
}
/*
* Attempt to parse a URL and match it with the blacklist.
*
* BUG:
* - This function makes several assumptions about HTTP requests, such as:
* 1) The URL will be contained within one packet;
* 2) The HTTP request begins at a packet boundary;
* 3) The Host header immediately follows the GET/POST line.
* Some browsers, such as Internet Explorer, violate these assumptions
* and therefore matching will not work.
*/
static BOOL BlackListPayloadMatch(PBLACKLIST blacklist, char *data, UINT16 len)
{
static const char get_str[] = "GET /";
static const char post_str[] = "POST /";
static const char http_host_str[] = " HTTP/1.1\r\nHost: ";
char domain[MAXURL];
char uri[MAXURL];
URL url = {domain, uri};
UINT16 i = 0, j;
BOOL result;
HANDLE console;
if (len <= sizeof(post_str) + sizeof(http_host_str))
{
return FALSE;
}
if (strncmp(data, get_str, sizeof(get_str)-1) == 0)
{
i += sizeof(get_str)-1;
}
else if (strncmp(data, post_str, sizeof(post_str)-1) == 0)
{
i += sizeof(post_str)-1;
}
else
{
return FALSE;
}
for (j = 0; i < len && data[i] != ' '; j++, i++)
{
uri[j] = data[i];
}
uri[j] = '\0';
if (i + sizeof(http_host_str)-1 >= len)
{
return FALSE;
}
if (strncmp(data+i, http_host_str, sizeof(http_host_str)-1) != 0)
{
return FALSE;
}
i += sizeof(http_host_str)-1;
for (j = 0; i < len && data[i] != '\r'; j++, i++)
{
domain[j] = data[i];
}
if (i >= len)
{
return FALSE;
}
if (j == 0)
{
return FALSE;
}
if (domain[j-1] == '.')
{
// Nice try...
j--;
if (j == 0)
{
return FALSE;
}
}
domain[j] = '\0';
printf("URL %s/%s: ", domain, uri);
// Reverse the domain:
for (i = 0; i < j / 2; i++)
{
char t = domain[i];
domain[i] = domain[j-i-1];
domain[j-i-1] = t;
}
// Search the blacklist:
result = BlackListMatch(blacklist, &url);
// Print the verdict:
console = GetStdHandle(STD_OUTPUT_HANDLE);
if (result)
{
SetConsoleTextAttribute(console, FOREGROUND_RED);
puts("BLOCKED!");
}
else
{
SetConsoleTextAttribute(console, FOREGROUND_GREEN);
puts("allowed");
}
SetConsoleTextAttribute(console,
FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
return result;
}
/*
* URL comparison.
*/
static int __cdecl UrlCompare(const void *a, const void *b)
{
PURL urla = *(PURL *)a;
PURL urlb = *(PURL *)b;
int cmp = strcmp(urla->domain, urlb->domain);
if (cmp != 0)
{
return cmp;
}
return strcmp(urla->uri, urlb->uri);
}
/*
* URL matching
*/
static int UrlMatch(PURL urla, PURL urlb)
{
UINT16 i;
for (i = 0; urla->domain[i] && urlb->domain[i]; i++)
{
int cmp = (int)urlb->domain[i] - (int)urla->domain[i];
if (cmp != 0)
{
return cmp;
}
}
if (urla->domain[i] == '\0' && urlb->domain[i] != '\0')
{
return 1;
}
for (i = 0; urla->uri[i] && urlb->uri[i]; i++)
{
int cmp = (int)urlb->uri[i] - (int)urla->uri[i];
if (cmp != 0)
{
return cmp;
}
}
if (urla->uri[i] == '\0' && urlb->uri[i] != '\0')
{
return 1;
}
return 0;
}
This file compiles without errors as C code, so be sure that you compile it as C. If you need to compile it as C++, then add explicit cast to char* at payload parameter in this line:
if (!WinDivertHelperParsePacket(packet, packet_len, &ip_header, NULL,
NULL, NULL, &tcp_header, NULL, &payload, &payload_len) ||
!BlackListPayloadMatch(blacklist, payload, (UINT16)payload_len))
Like this:
if (!WinDivertHelperParsePacket(packet, packet_len, &ip_header, NULL,
NULL, NULL, &tcp_header, NULL, &payload, &payload_len) ||
!BlackListPayloadMatch(blacklist, (char*)payload, (UINT16)payload_len))

Mac C++ Broadcast -> more then one network-interface

I have a broadcast program on my mac, everything is working fine, but if i have more then one network interface, he didn't recieve anything.
So what i now want to do is:
Check which network interfaces are activ on the mac
send to every activ interface a broadcast ( so i have to select which interface i want to use)
recieve the answer (if there is one :) )
Interesting:
the broadcast client is on my WLAN (with a router beetween the devices) and a normal internet connection is on my LAN. If i deactivate the LAN in the system configs, he also didn't find my other device, but if i pull the cable he found the other device... So maybe i didn't have to look which interface is activ and have a look to which interface is connected.
Do u have some tipps or good google keywords for me to do that?
Long time ago, but if someone find my post, here is my solution:
#include <stdint.h>
static uint32 Inet_AtoN(const char * buf)
{
// net_server inexplicably doesn't have this function; so I'll just fake it
uint32 ret = 0;
int shift = 24; // fill out the MSB first
bool startQuad = true;
while ((shift >= 0) && (*buf))
{
if (startQuad)
{
unsigned char quad = (unsigned char)atoi(buf);
ret |= (((uint32)quad) << shift);
shift -= 8;
}
startQuad = (*buf == '.');
buf++;
}
return ret;
}
int Broadcast::BroadcastToAllInterfaces()
{
DEBUG_LOG(1,"Start Broadcast To All Interfaces", "DEv1");
globalDatabase->SetInBroadcast();
moreThenOne = 0;
#if defined(USE_GETIFADDRS)
struct ifaddrs * ifap;
if (getifaddrs(&ifap) == 0)
{
struct ifaddrs * p = ifap;
while (p)
{
uint32 ifaAddr = SockAddrToUint32(p->ifa_addr);
uint32 maskAddr = SockAddrToUint32(p->ifa_netmask);
uint32 dstAddr = SockAddrToUint32(p->ifa_dstaddr);
if (ifaAddr > 0)
{
char ifaAddrStr[32]; Inet_NtoA(ifaAddr, ifaAddrStr);
char maskAddrStr[32]; Inet_NtoA(maskAddr, maskAddrStr);
char dstAddrStr[32]; Inet_NtoA(dstAddr, dstAddrStr);
std::stringstream addr, descss;
std::string addrs, descs;
addr << dstAddrStr;
descss << p->ifa_name;
descss >> descs;
addr >> addrs;
DoABroadcast(dstAddr);
}
p = p->ifa_next;
}
freeifaddrs(ifap);
}
#elif defined(WIN32)
// Windows XP style implementation
// Adapted from example code at http://msdn2.microsoft.com/en-us/library/aa365917.aspx
// Now get Windows' IPv4 addresses table. Once again, we gotta call GetIpAddrTable()
// multiple times in order to deal with potential race conditions properly.
MIB_IPADDRTABLE * ipTable = NULL;
{
ULONG bufLen = 0;
for (int i = 0; i<5; i++)
{
DWORD ipRet = GetIpAddrTable(ipTable, &bufLen, false);
if (ipRet == ERROR_INSUFFICIENT_BUFFER)
{
free(ipTable); // in case we had previously allocated it STILL_RUN
ipTable = (MIB_IPADDRTABLE *)malloc(bufLen);
}
else if (ipRet == NO_ERROR) break;
else
{
free(ipTable);
ipTable = NULL;
break;
}
}
}
if (ipTable)
{
IP_ADAPTER_INFO * pAdapterInfo = NULL;
{
ULONG bufLen = 0;
for (int i = 0; i<5; i++)
{
DWORD apRet = GetAdaptersInfo(pAdapterInfo, &bufLen);
if (apRet == ERROR_BUFFER_OVERFLOW)
{
free(pAdapterInfo); // in case we had previously allocated it
pAdapterInfo = (IP_ADAPTER_INFO *)malloc(bufLen);
}
else if (apRet == ERROR_SUCCESS) break;
else
{
free(pAdapterInfo);
pAdapterInfo = NULL;
break;
}
}
}
for (DWORD i = 0; i<ipTable->dwNumEntries; i++)
{
const MIB_IPADDRROW & row = ipTable->table[i];
// Now lookup the appropriate adaptor-name in the pAdaptorInfos, if we can find it
const char * name = NULL;
const char * desc = NULL;
if (pAdapterInfo)
{
IP_ADAPTER_INFO * next = pAdapterInfo;
while ((next) && (name == NULL))
{
IP_ADDR_STRING * ipAddr = &next->IpAddressList;
while (ipAddr)
{
if (Inet_AtoN(ipAddr->IpAddress.String) == ntohl(row.dwAddr))
{
name = next->AdapterName;
desc = next->Description;
break;
}
ipAddr = ipAddr->Next;
}
next = next->Next;
}
}
char buf[128];
int setUnnamed = 0;
if (name == NULL)
{
sprintf(buf, "unnamed");
name = buf;
setUnnamed = 1;
}
uint32 ipAddr = ntohl(row.dwAddr);
uint32 netmask = ntohl(row.dwMask);
uint32 baddr = ipAddr & netmask;
if (row.dwBCastAddr) baddr |= ~netmask;
char ifaAddrStr[32]; Inet_NtoA(ipAddr, ifaAddrStr);
char maskAddrStr[32]; Inet_NtoA(netmask, maskAddrStr);
char dstAddrStr[32]; Inet_NtoA(baddr, dstAddrStr);
std::stringstream addr, descss;
std::string addrs, descs;
if (setUnnamed == 0)
{
addr << dstAddrStr;
descss << desc;
descss >> descs;
addr >> addrs;
DoABroadcast(baddr);
}
}
free(pAdapterInfo);
free(ipTable);
}
#else
// Dunno what we're running on here!
# error "Don't know how to implement PrintNetworkInterfaceInfos() on this OS!"
#endif
globalDatabase->SetLeaveBroadcast();
return 1;
}
int Broadcast::DoABroadcast(uint32 broadAddr)
{
int askSinlen = sizeof(struct sockaddr_in);
int askBuflen = MAXBUF;
int message;
char buf[512];
int status;
char askBuffer[MAXBUF];
struct sockaddr_in sock_in, client_adress, client_adress2;
#ifdef __APPLE__
socklen_t clientLength;
int askYes = 1;
#else
char askYes = 1;
int clientLength;
WSADATA w;
int result = WSAStartup(MAKEWORD(2, 2), &w);
#endif
int recSocket = socket(AF_INET, SOCK_DGRAM, 0);
if (recSocket <0)
{
#ifdef __APPLE__
close(recSocket);
#else
closesocket(recSocket);
#endif
inBroadcast = false;
return 10;
}
sock_in.sin_addr.s_addr = htonl(INADDR_ANY);
sock_in.sin_port = htons(4028);
sock_in.sin_family = PF_INET;
client_adress.sin_family = PF_INET;
client_adress.sin_port = htons(4029);
client_adress.sin_addr.s_addr = htonl(broadAddr);
askSinlen = sizeof(sock_in);
client_adress2.sin_family = AF_INET;
client_adress2.sin_port = htons(4028);
client_adress2.sin_addr.s_addr = htonl(0xc0a8b2ff);
status = setsockopt(recSocket, SOL_SOCKET, SO_BROADCAST, &askYes, sizeof(askYes));
if (status < 0)
{
#ifdef __APPLE__
close(recSocket);
#else
closesocket(recSocket);
#endif
inBroadcast = false;
return 10;
}
status = bind(recSocket, (struct sockaddr *)&sock_in, askSinlen);
if (status < 0)
{
#ifdef __APPLE__
close(recSocket);
#else
closesocket(recSocket);
#endif
inBroadcast = false;
return 10;
}
askBuflen = sprintf(askBuffer, "Ciao Mac ist hier");
status = sendto(recSocket, askBuffer, askBuflen, 0, (struct sockaddr *)&client_adress, sizeof(client_adress));
fd_set fds;
struct timeval tv;
tv.tv_sec = 2;
tv.tv_usec = 0;
FD_ZERO(&fds);
FD_SET(recSocket, &fds);
int ret;
if ((ret = select(recSocket +1, &fds, NULL, NULL, &tv)) > 0)
{
int e = 0;
while ((ret = select(recSocket + 1, &fds, NULL, NULL, &tv)) > 0)
{
clientLength = sizeof(client_adress2);
message = recvfrom(recSocket, buf, sizeof(buf), 0, (struct sockaddr*) &client_adress2, &clientLength);
if (message == -1)
{
#ifdef __APPLE__
close(recSocket);
#else
closesocket(recSocket);
#endif
inBroadcast = false;
return -5;
}
else
{
std::string hereisyourbroadcast(buf);
}
}
}
else
{
#ifdef __APPLE__
close(recSocket);
#else
closesocket(recSocket);
#endif
inBroadcast = false;
return -6;
}
#ifdef __APPLE__
close(recSocket);
#else
closesocket(recSocket);
#endif
inBroadcast = false;
return 1;
}

Developing with Firefox SDK with IDE (Visual Studio 2013 maybe)

I started developing a Firefox add-on, however I could not find any IDE specifically for Firefox. For most part it doesn't really matter because I can just open Javascript files and edit them (I use VS2013 and Web Essentials (I think)).
Up to this point everything is acceptable, but when I have to use cmd every time to run this plugin and then read console logs from cmd, it becomes a nightmare.
So my is - is there some way to launch, develop and log Firefox plugin just like any code in Visual Studio 2013? Other IDEs are welcome too.
Well I think it would be possible to create Visual Studio add-on, but it just too much work. However, I managed to partly integrate Firefox add-on creation into VS2013 with c++ code. It redirects cmd window so that means, that you'll output from cmd in "Output" window while debugging.
I'm leaving complete code with steps in case someone else needs this (C++11 is required):
Create Win32 C++ project (not cmd one).
Paste code (below) into cpp file.
Change YOUR_EXTENSION_NAME to your add-on name.
Run code once, it should throw message box with info where to put Add-on SDK.
Copy SDK files to that folder.
Run code again and exit (you may exit however you want, it should terminate remaining windows).
Now there are 3 options for file (.js, .css, etc.) linking:
Create files manually in SDK folder and add them manually to project.
Create files via VS2013 menu and then uncomment and modify, add, delete lines in do while loop.
Create files via VS2013 menu, but choose SDK folders.
Code:
#include <windows.h>
#include <tchar.h>
#include <thread>
#include <chrono>
#include <typeinfo>
#include <Shlwapi.h>
#pragma comment(lib,"Shlwapi.lib")
// Timer code start
/*
//
//Credit goes to James Daughtry for this piece of code
//
*/
class Timer {
typedef std::chrono::high_resolution_clock high_resolution_clock;
typedef std::chrono::milliseconds milliseconds;
public:
Timer(bool run = false)
{
if (run) Reset();
}
void Reset()
{
_start = high_resolution_clock::now();
}
milliseconds Elapsed() const
{
return std::chrono::duration_cast<milliseconds>(high_resolution_clock::now() - _start);
}
private:
high_resolution_clock::time_point _start;
};
// Timer code end
// Cmd redirection code start
/*
//
//Credit goes to some guys from StackOverflow for directions and Randor from CodeProject for base code
//
*/
struct _JOBWRAPPER
{
HANDLE hJob;
_JOBWRAPPER() : hJob(NULL) {}
~_JOBWRAPPER() { if (this->hJob != NULL) CloseHandle(hJob); }
operator HANDLE() const { return this->hJob; }
}hJob;
typedef void(*TextOutFunction)(LPCSTR);
struct _THREADARGUMENTS
{
HANDLE hOutRead;
clock_t stTimeout;
LPCSTR pchBreakText;
TextOutFunction Function;
bool bGotInfo;
_THREADARGUMENTS() : bGotInfo(false), hOutRead(NULL), stTimeout(NULL), pchBreakText(nullptr), Function(nullptr) {}
};
void ReadCMDThread(_THREADARGUMENTS* Arguments)
{
if (Arguments->hOutRead != NULL)
{
UINT CheckForAnyResponseOnLoop = 5, CurrentLoop = 0;
clock_t ScanInterval = 50;
DWORD dwAvailable = 0;
DWORD bytesRead = 0;
CHAR szOut[4096] = { 0 };
if (Arguments->stTimeout == 0)
{
while (true)
{
CurrentLoop++;
PeekNamedPipe(Arguments->hOutRead, szOut, sizeof(szOut), &bytesRead, &dwAvailable, NULL);
if (0 != bytesRead)
{
if (ReadFile(Arguments->hOutRead, szOut, sizeof(szOut), &bytesRead, NULL))
Arguments->bGotInfo = true;
Arguments->Function(szOut);
if (Arguments->pchBreakText != nullptr && Arguments->pchBreakText != "" && strstr(szOut, Arguments->pchBreakText) != nullptr)
break;
memset(szOut, '\0', sizeof(char) * 4096);
}
if (CheckForAnyResponseOnLoop == CurrentLoop && Arguments->pchBreakText == "")
break;
std::this_thread::sleep_for((std::chrono::milliseconds)ScanInterval);
}
}
else
{
Timer timer(true);
while (timer.Elapsed() < (std::chrono::milliseconds)Arguments->stTimeout)
{
CurrentLoop++;
PeekNamedPipe(Arguments->hOutRead, szOut, sizeof(szOut), &bytesRead, &dwAvailable, NULL);
if (0 != bytesRead)
{
if (ReadFile(Arguments->hOutRead, szOut, sizeof(szOut), &bytesRead, NULL))
Arguments->bGotInfo = true;
Arguments->Function(szOut);
timer.Reset();
if (Arguments->pchBreakText != nullptr && Arguments->pchBreakText != "" && strstr(szOut, Arguments->pchBreakText) != nullptr)
break;
memset(szOut, '\0', sizeof(char) * 4096);
}
if (CheckForAnyResponseOnLoop == CurrentLoop && Arguments->pchBreakText == "")
break;
std::this_thread::sleep_for((std::chrono::milliseconds)ScanInterval);
}
}
}
}
class CMDREDIRECTION{
private:
HANDLE hInRead, hInWrite, hOutRead, hOutWrite;
PROCESS_INFORMATION pi;
STARTUPINFO si;
SECURITY_ATTRIBUTES sa;
TextOutFunction CustomFunction;
public:
CMDREDIRECTION(TextOutFunction Function) : hInRead(NULL), hInWrite(NULL), hOutRead(NULL),
hOutWrite(NULL), CustomFunction(Function) {}
~CMDREDIRECTION(){
if (hInRead != NULL)
CloseHandle(hInRead);
if (hInWrite != NULL)
CloseHandle(hInWrite);
if (hOutRead != NULL)
CloseHandle(hOutRead);
if (hOutWrite != NULL)
CloseHandle(hOutWrite);
}
DWORD WriteToCmd(LPSTR pchString, bool PressEnter = false)
{
DWORD dwWritten = 0;
size_t GivenStringLength = strlen(pchString);
LPSTR TemporaryString = pchString;
bool bSuccess = false;
if (GivenStringLength != 0)
{
if (PressEnter)
{
size_t StringSize = GivenStringLength + 2;
TemporaryString = new CHAR[StringSize];
for (size_t i = 0; i < GivenStringLength; i++)
TemporaryString[i] = pchString[i];
TemporaryString[StringSize - 2] = '\n';
TemporaryString[StringSize - 1] = '\0';
bSuccess = (WriteFile(hInWrite, TemporaryString, strlen(TemporaryString), &dwWritten, NULL) && dwWritten);
delete[] TemporaryString;
}
else
bSuccess = (WriteFile(hInWrite, TemporaryString, strlen(TemporaryString), &dwWritten, NULL) && dwWritten);
}
return bSuccess;
}
bool GetAnswer(clock_t stTimeout, LPCSTR pchBreakText)
{
_THREADARGUMENTS Arguments;
Arguments.hOutRead = hOutRead;
Arguments.pchBreakText = pchBreakText;
Arguments.stTimeout = stTimeout;
Arguments.Function = CustomFunction;
std::thread CMDWatcher(ReadCMDThread, &Arguments);
CMDWatcher.join();
return Arguments.bGotInfo;
}
bool WriteToCmdAndWaitForAnswer(LPSTR pchString, clock_t stTimeout, LPCSTR pchBreakText, bool PressEnter = false)
{
if (WriteToCmd(pchString, PressEnter))
{
return (GetAnswer(stTimeout, pchBreakText));
}
else
{
return false;
}
}
bool Start()
{
if (hJob.hJob == NULL)
{
hJob.hJob = CreateJobObject(NULL, NULL);
if (hJob.hJob != NULL)
{
JOBOBJECT_EXTENDED_LIMIT_INFORMATION jeli = { 0 };
jeli.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
if (!SetInformationJobObject((HANDLE)hJob, JobObjectExtendedLimitInformation, &jeli, sizeof(jeli)))
{
return false;
}
}
else
{
return false;
}
}
ZeroMemory(&sa, sizeof(sa));
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.bInheritHandle = TRUE;
CreatePipe(&hInRead, &hInWrite, &sa, 0);
CreatePipe(&hOutRead, &hOutWrite, &sa, 0);
ZeroMemory(&si, sizeof(si));
GetStartupInfo(&si);
si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
si.hStdOutput = hOutWrite;
si.hStdError = hOutWrite;
si.hStdInput = hInRead;
si.wShowWindow = SW_HIDE;
TCHAR Path[MAX_PATH] = { 0 };
GetSystemDirectory(Path, MAX_PATH);
_tcscat_s(Path, TEXT("\\cmd.exe"));
if (CreateProcess(Path, NULL, NULL, NULL, TRUE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi))
{
BOOL bResult = AssignProcessToJobObject(hJob, pi.hProcess);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
return (bResult != 0);
}
else
{
return false;
}
}
};
// Cmd redirection code end
// TString code start
#ifdef UNICODE
#define TCat TCatW
#define TString _TString<WCHAR>
#else
#define TCat TCatA
#define TString _TString<CHAR>
#endif
struct AnyString
{
PVOID String;
bool bWide;
AnyString(LPSTR String)
{
this->String = String;
bWide = false;
}
AnyString(LPWSTR String)
{
this->String = String;
bWide = true;
}
operator LPSTR() { return (LPSTR)String; }
operator LPSTR() const { return (LPSTR)String; }
operator LPWSTR() { return (LPWSTR)String; }
operator LPWSTR() const { return (LPWSTR)String; }
};
template<class T>
class _TString
{
friend void SeAnyString(LPSTR String, _TString<CHAR> &TempString);
T *String;
size_t size;
void free()
{
if (String != nullptr && size != 0)
{
delete[] String;
String = nullptr;
size = 0;
}
}
_TString<CHAR> ToCHAR(LPWSTR wch)
{
_TString<CHAR> TempString;
LPSTR Buffer = nullptr;
size_t size = wcslen(wch),
realsize = size + 1;
if (size != 0)
{
Buffer = new CHAR[realsize];
wcstombs_s(nullptr, Buffer, realsize, wch, size);
TempString.SetAllocatedString(Buffer, size);
}
return TempString;
}
_TString<WCHAR> ToWCHAR(LPSTR ch)
{
_TString<WCHAR> TempString;
LPWSTR Buffer = nullptr;
size_t size = strlen(ch),
realsize = size + 1;
if (size != 0)
{
Buffer = new WCHAR[realsize];
mbstowcs_s(nullptr, Buffer, realsize, ch, size);
TempString.SetAllocatedString(Buffer, size);
}
return TempString;
}
public:
_TString(T *String)
{
free();
if (typeid(T) == typeid(CHAR))
{
size = strlen(String);
if (size != 0)
{
this->String = new T[size + 1];
for (size_t i = 0; i < size; i++)
this->String[i] = String[i];
this->String[size] = '\0';
}
}
else if (typeid(T) == typeid(WCHAR))
{
size = wcslen(String);
if (size != 0)
{
this->String = new T[size + 1];
for (size_t i = 0; i < size; i++)
this->String[i] = String[i];
this->String[size] = L'\0';
}
}
}
_TString() : String(nullptr), size(0) {}
~_TString() { free(); }
_TString(_TString&& OldTempStr)
{
this->String = OldTempStr.String;
this->size = OldTempStr.size;
OldTempStr.size = 0;
OldTempStr.String = nullptr;
}
_TString& operator=(_TString&& OldTempStr)
{
this->String = OldTempStr.String;
this->size = OldTempStr.size;
OldTempStr.size = 0;
OldTempStr.String = nullptr;
return *this;
}
operator T*() const { return String; }
operator T*() { return String; }
T& operator[] (size_t i) { return String[i]; }
void SetAllocatedString(T *String, size_t size)
{
free();
this->String = String;
this->size = size;
}
void join(LPWSTR StringToJoin)
{
join(AnyString(StringToJoin));
}
void join(LPSTR StringToJoin)
{
join(AnyString(StringToJoin));
}
void join(AnyString StringToJoin)
{
if (typeid(T) == typeid(CHAR))
{
size_t length = 0;
_TString<CHAR> TempString;
LPSTR StringLiteral = nullptr;
if (StringToJoin.bWide)
{
TempString = ToCHAR(StringToJoin);
StringLiteral = TempString;
}
else
{
StringLiteral = StringToJoin;
}
if (StringLiteral != nullptr)
length = strlen(StringLiteral);
if (length != 0)
{
size_t newsize = size + length, realsize = newsize + 1;
T *Buffer = new T[realsize];
for (size_t i = 0; i < size; i++)
Buffer[i] = String[i];
for (size_t i = size, j = 0; i < newsize; i++, j++)
Buffer[i] = StringLiteral[j];
Buffer[newsize] = '\0';
free();
size = newsize;
String = Buffer;
}
}
else if (typeid(T) == typeid(WCHAR))
{
size_t length = 0;
_TString<WCHAR> TempString;
LPWSTR StringLiteral = nullptr;
if (StringToJoin.bWide)
{
StringLiteral = StringToJoin;
}
else
{
TempString = ToWCHAR(StringToJoin);
StringLiteral = TempString;
}
if (StringLiteral != nullptr)
length = wcslen(StringLiteral);
if (length != 0)
{
size_t newsize = size + length, realsize = newsize + 1;
T *Buffer = new T[realsize];
for (size_t i = 0; i < size; i++)
Buffer[i] = String[i];
for (size_t i = size, j = 0; i < newsize; i++, j++)
Buffer[i] = StringLiteral[j];
Buffer[newsize] = L'\0';
free();
size = newsize;
String = Buffer;
}
}
}
size_t GetSize() { return size; }
T* GetString() { return String; }
};
_TString<CHAR> TCatA(std::initializer_list<AnyString> list)
{
_TString<CHAR> String;
for (auto iterator = list.begin(), end = list.end(); iterator != end; ++iterator)
String.join(*iterator);
return String;
}
_TString<WCHAR> TCatW(std::initializer_list<AnyString> list)
{
_TString<WCHAR> String;
for (auto iterator = list.begin(), end = list.end(); iterator != end; ++iterator)
String.join(*iterator);
return String;
}
// TString code end
// Main code start
#define EXTENSION_NAME YOUR_EXTENSION_NAME //"my-extension" in ANSI
void WriteToOutputWindow(LPCSTR Text) { OutputDebugStringA(Text); }
void GetProjectDirectory(TString &Path)
{
TCHAR MaxPath[MAX_PATH] = { 0 };
GetModuleFileName(NULL, MaxPath, MAX_PATH);
for (int i = _tcslen(MaxPath), ch = 0; i > 0; i--)
{
if (MaxPath[i] == TEXT('\\') && ++ch == 2)
break;
else
MaxPath[i] = TEXT('\0');
}
Path.join(MaxPath);
}
void GetDataDirectory(TString &Path)
{
GetProjectDirectory(Path);
TCHAR TempBuffer[MAX_PATH] = { 0 }, FinalBuffer[MAX_PATH] = { 0 };
for (size_t i = Path.GetSize() - 1, ch = 0, j = 0; i > 0; i--, j++)
{
if (Path[i] == TEXT('\\') && ++ch == 2)
break;
else
TempBuffer[j] = Path[i];
}
for (size_t i = _tcslen(TempBuffer), j = 0; i > 0; i--, j++)
FinalBuffer[j] = TempBuffer[i - 1];
Path.join(FinalBuffer);
}
bool Restart()
{
int msgboxID = MessageBox(NULL, TEXT("Firefox has been closed. Save changes and press \"Yes\" to run again."), TEXT("Run again?"), MB_YESNO | MB_ICONQUESTION);
switch (msgboxID)
{
case IDYES:
return true;
case IDNO:
return false;
}
}
int WINAPI _tWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrev, _In_ LPTSTR lpCmdLine, _In_ int nCmdShow)
{
CMDREDIRECTION Window(WriteToOutputWindow);
TString ExtensionDir;
TString DataDir;
if (Window.Start())
{
GetProjectDirectory(ExtensionDir);
GetDataDirectory(DataDir);
ExtensionDir.join(TEXT("Firefox SDK\\"));
if (!PathIsDirectory(ExtensionDir))
Window.WriteToCmdAndWaitForAnswer(TCatA({ "mkdir \"", ExtensionDir.GetString(), "\"" }), 0, "", true);
if (PathIsDirectoryEmpty(ExtensionDir))
{
MessageBox(NULL, TCat({ TEXT("Firefox SDK directory is empty, please copy SDK files to this directory: "), ExtensionDir.GetString() }), TEXT("Failure!"), MB_ICONINFORMATION);
return EXIT_FAILURE;
}
Window.WriteToCmdAndWaitForAnswer(TCatA({ "cd ", ExtensionDir.GetString() }), 0, "", true);
Window.WriteToCmdAndWaitForAnswer("bin\\activate", 0, "", true);
ExtensionDir.join(TCat({ TEXT(EXTENSION_NAME), TEXT("\\") }));
if (!PathIsDirectory(ExtensionDir))
Window.WriteToCmdAndWaitForAnswer(TCatA({ "mkdir ", EXTENSION_NAME }), 0, "", true);
Window.WriteToCmdAndWaitForAnswer(TCatA({ "cd ", EXTENSION_NAME }), 0, "", true);
if (PathIsDirectoryEmpty(ExtensionDir))
Window.WriteToCmdAndWaitForAnswer("cfx init", 0, "", true);
do
{
/*
Window.WriteToCmdAndWaitForAnswer(TCatA({ "cd ", DataDir.GetString() }), 0, "", true);
Window.WriteToCmdAndWaitForAnswer(TCatA({ "XCOPY \"main.js\" \"", ExtensionDir.GetString(), TEXT(EXTENSION_NAME), "\\lib\\\" /Y" }), 0, "", true);
Window.WriteToCmdAndWaitForAnswer(TCatA({ "XCOPY \"*.js\" \"", ExtensionDir.GetString(), TEXT(EXTENSION_NAME), "\\data\\\" /Y /EXCLUDE:exclude.txt" }), 0, "", true);
Window.WriteToCmdAndWaitForAnswer(TCatA({ "XCOPY \"*.html\" \"", ExtensionDir.GetString(), TEXT(EXTENSION_NAME), "\\data\\\" /Y" }), 0, "", true);
Window.WriteToCmdAndWaitForAnswer(TCatA({ "XCOPY \"*.png\" \"", ExtensionDir.GetString(), TEXT(EXTENSION_NAME), "\\data\\\" /Y" }), 0, "", true);
Window.WriteToCmdAndWaitForAnswer(TCatA({ "XCOPY \"*.css\" \"", ExtensionDir.GetString(), TEXT(EXTENSION_NAME), "\\data\\\" /Y" }), 0, "", true);
*/
Window.WriteToCmdAndWaitForAnswer("cfx run --profiledir=\"./dir\"", 0, "Program terminated successfully.", true);
} while (Restart());
}
return EXIT_SUCCESS;
}
// Main code end

Hooking NtQueryDirectoryFile can't hide files

I want to hide files (in my program). I decided to use NtQueryDirectoryFile. But the files are not hidden, the code does not work. I don't use a driver, I use user mode. Can anybody help me please?
The code snippet:
typedef NTSTATUS (WINAPI * NTQUERYDIRECTORYFILE) (IN HANDLE FileHandle,IN HANDLE Event OPTIONAL,IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,IN PVOID ApcContext OPTIONAL,OUT PIO_STATUS_BLOCK IoStatusBlock,OUT PVOID FileInformation,IN ULONG FileInformationLength,IN MYFILE_INFORMATION_CLASS FileInformationClass,IN BOOLEAN ReturnSingleEntry,IN PUNICODE_STRING FileName OPTIONAL,IN BOOLEAN RestartScan);
NTQUERYDIRECTORYFILE OriginalNtQueryDirectoryFile;
#define STATUS_NO_SUCH_FILE 0xC000000F
NTSTATUS
HookedNtQueryDirectoryFile(
IN HANDLE FileHandle,
IN HANDLE Event OPTIONAL,
IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
IN PVOID ApcContext OPTIONAL,
OUT PIO_STATUS_BLOCK IoStatusBlock,
OUT PVOID FileInformation,
IN ULONG FileInformationLength,
IN MYFILE_INFORMATION_CLASS FileInformationClass,
IN BOOLEAN ReturnSingleEntry,
IN PUNICODE_STRING FileName OPTIONAL,
IN BOOLEAN RestartScan)
{
NTSTATUS status = OriginalNtQueryDirectoryFile(FileHandle,Event,ApcRoutine,ApcContext,IoStatusBlock,FileInformation,FileInformationLength,FileInformationClass,ReturnSingleEntry,FileName,RestartScan);
vector<wstring> listDataForHidding;
listDataForHidding.push_back(L"afile.txt");
listDataForHidding.push_back(L"bfile.txt");
listDataForHidding.push_back(L"cfile.txt");
listDataForHidding.push_back(L"dfile.txt");
if (NT_SUCCESS(status))
{
PMYFILE_DIRECTORY_INFORMATION FileDirectoryInfo, LastFileDirectoryInfo;
PMYFILE_FULL_DIR_INFORMATION LastFileFullDirectoryInfo, FileFullDirectoryInfo;
PMYFILE_BOTH_DIR_INFORMATION LastFileBothDirectoryInfo, FileBothDirectoryInfo;
PMYFILE_NAMES_INFORMATION LastFileNamesInfo, FileNamesInfo;
ULONG Offset = 0;
BOOL bNeedHide = FALSE;
switch (FileInformationClass)
{
case FileDirectoryInformation :
FileDirectoryInfo = NULL;
do
{
//FileDirectoryInfo = (PVOID)((ULONG)FileInformation + Offset);
FileDirectoryInfo = (PMYFILE_DIRECTORY_INFORMATION)((ULONG)FileInformation + Offset);
LastFileDirectoryInfo = FileDirectoryInfo;
wstring wstrCurrFileName = FileDirectoryInfo->FileName;
bNeedHide = FALSE;
for(size_t index = 0; index < listDataForHidding.size(); index ++)
{
if(wstrCurrFileName.find(listDataForHidding[index]) != wstring::npos)
{
bNeedHide = TRUE;
break;
}
}
//if (FileDirectoryInfo->FileName[0] == 0x5F00)
if(bNeedHide == TRUE)
{
if (!FileDirectoryInfo->NextEntryOffset)
{
if (LastFileDirectoryInfo) LastFileDirectoryInfo->NextEntryOffset = 0;
else status = STATUS_NO_SUCH_FILE;
return status;
} else
if (LastFileDirectoryInfo) LastFileDirectoryInfo->NextEntryOffset += FileDirectoryInfo->NextEntryOffset;
}
Offset += FileDirectoryInfo->NextEntryOffset;
} while (FileDirectoryInfo->NextEntryOffset);
break;
case FileFullDirectoryInformation :
FileFullDirectoryInfo = NULL;
do
{
LastFileFullDirectoryInfo = FileFullDirectoryInfo;
//FileFullDirectoryInfo = (PVOID)((ULONG)FileInformation + Offset);
FileFullDirectoryInfo = (PMYFILE_FULL_DIR_INFORMATION)((ULONG)FileInformation + Offset);
wstring wstrCurrFileName = FileDirectoryInfo->FileName;
bNeedHide = FALSE;
for(size_t index = 0; index < listDataForHidding.size(); index ++)
{
if(wstrCurrFileName.find(listDataForHidding[index]) != wstring::npos)
{
bNeedHide = TRUE;
break;
}
}
//if (FileFullDirectoryInfo->FileName[0] == 0x5F00)
if(bNeedHide == TRUE)
{
if (!FileFullDirectoryInfo->NextEntryOffset)
{
if (LastFileFullDirectoryInfo) LastFileFullDirectoryInfo->NextEntryOffset = 0;
else status = STATUS_NO_SUCH_FILE;
return status;
} else
if (LastFileFullDirectoryInfo) LastFileFullDirectoryInfo->NextEntryOffset += FileFullDirectoryInfo->NextEntryOffset;
}
Offset += FileFullDirectoryInfo->NextEntryOffset;
} while (FileFullDirectoryInfo->NextEntryOffset);
break;
case FileBothDirectoryInformation :
FileBothDirectoryInfo = NULL;
do
{
LastFileBothDirectoryInfo = FileBothDirectoryInfo;
//FileBothDirectoryInfo = (PVOID)((ULONG)FileInformation + Offset);
FileBothDirectoryInfo = (PMYFILE_BOTH_DIR_INFORMATION)((ULONG)FileInformation + Offset);
wstring wstrCurrFileName = FileDirectoryInfo->FileName;
bNeedHide = FALSE;
for(size_t index = 0; index < listDataForHidding.size(); index ++)
{
if(FileBothDirectoryInfo->FileNameLength > 1 && wstrCurrFileName.find(listDataForHidding[index]) != wstring::npos)
{
bNeedHide = TRUE;
break;
}
}
//if (FileBothDirectoryInfo->FileNameLength > 1 && FileBothDirectoryInfo->FileName[0] == 0x5F00)
if(bNeedHide == TRUE)
{
if (!FileBothDirectoryInfo->NextEntryOffset)
{
if (LastFileBothDirectoryInfo) LastFileBothDirectoryInfo->NextEntryOffset = 0;
else status = STATUS_NO_SUCH_FILE;
return status;
} else
if (LastFileBothDirectoryInfo) LastFileBothDirectoryInfo->NextEntryOffset += FileBothDirectoryInfo->NextEntryOffset;
}
Offset += FileBothDirectoryInfo->NextEntryOffset;
} while (FileBothDirectoryInfo->NextEntryOffset);
break;
case FileNamesInformation :
FileNamesInfo = NULL;
do
{
LastFileNamesInfo = FileNamesInfo;
//FileNamesInfo = (PVOID)((ULONG)FileInformation + Offset);
FileNamesInfo = (PMYFILE_NAMES_INFORMATION)((ULONG)FileInformation + Offset);
wstring wstrCurrFileName = FileDirectoryInfo->FileName;
bNeedHide = FALSE;
for(size_t index = 0; index < listDataForHidding.size(); index ++)
{
if(wstrCurrFileName.find(listDataForHidding[index]) != wstring::npos)
{
bNeedHide = TRUE;
break;
}
}
//if (FileNamesInfo->FileName[0] == 0x5F00)
if(bNeedHide == TRUE)
{
if (!FileNamesInfo->NextEntryOffset)
{
if(LastFileNamesInfo) LastFileNamesInfo->NextEntryOffset = 0;
else status = STATUS_NO_SUCH_FILE;
return status;
} else
if (LastFileNamesInfo) LastFileNamesInfo->NextEntryOffset += FileNamesInfo->NextEntryOffset;
}
Offset += FileNamesInfo->NextEntryOffset;
} while (FileNamesInfo->NextEntryOffset);
break;
}
}
return status;
}

Resources