Не компилится один простой проект - стелс-программа, невидимая в системе. Компилятор (vs6.0) выдает ошибку E:\stealth-vs60\main.cpp(59) : error C2065: 'DWORD_PTR' : undeclared identifier на строке: PIMAGE_NT_HEADERS pNTHeaders = MakePtr(PIMAGE_NT_HEADERS,hmodCaller,pDosHeader->e_lfanew); MakePtr это макрос: #define MakePtr(cast, base, offset) (cast)((DWORD_PTR)(base) + (DWORD_PTR)(offset)) В чем может быть проблема. На всякий случай прилагаю исходники: _1662504131__xstealth.zip
Code (Text): typedef ULONG_PTR SIZE_T, *PSIZE_T; typedef LONG_PTR SSIZE_T, *PSSIZE_T; typedef ULONG_PTR DWORD_PTR, *PDWORD_PTR; у меня всё откомпилилось с первого раза да и вообще, имхо, можно использовать просто DWORD
Avoidik Т.е. без всяких изменений откомпилилось в vs6.0? Ты можешь мне кинуть список действий, которые ты сделал. Может я туплю? typedef ULONG_PTR SIZE_T, *PSIZE_T; typedef LONG_PTR SSIZE_T, *PSSIZE_T; typedef ULONG_PTR DWORD_PTR, *PDWORD_PTR; Но после добавление этих трех строчек возникают другие ошибки: E:\stealth-vs60\main.cpp(12) : error C2146: syntax error : missing ';' before identifier 'SIZE_T' E:\stealth-vs60\main.cpp(12) : fatal error C1004: unexpected end of file found Ругается прямо на пейвый же typedef
Code (Text): #if !defined(_W64) #if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300 #define _W64 __w64 #else #define _W64 #endif #endif #if defined(_WIN64) typedef unsigned __int64 ULONG_PTR, *PULONG_PTR; #else typedef _W64 unsigned long ULONG_PTR, *PULONG_PTR; #endif typedef ULONG_PTR DWORD_PTR, *PDWORD_PTR; Если не собираешься компилить для 64-битных машин, но XXX_PTR тебе вообще не нужен. Можешь изменить DWORD_PTR на: PCHAR - если приводится указатель на что-то. ULONG или DWORD - если приводится смещение, длина и т.п. Например, так: Code (Text): #define MakePtr(cast, base, offset) (cast)((PCHAR)(base) + (ULONG)(offset))
Ура, поставил определение типа (спасибо, ребята и особенно Four-F) и теперь main.cpp и replace.cpp компилятся. Но программа сама не собирается, прямо зло берет: почему я такой криворукий --------------------Configuration: hz - Win32 Debug-------------------- Linking... LIBCD.lib(crt0.obj) : error LNK2001: unresolved external symbol _main Debug/hz.exe : fatal error LNK1120: 1 unresolved externals Error executing link.exe. hz.exe - 2 error(s), 0 warning(s) Читаю MSDN по этому поводу, но пока так ничего и не нашел. Может я неправильно проект создаю? Делаю так: создаю новый проект "Win32 application", подключаю к нему файлы и собираю.
для win32 app точкой входа будет WinMain, а не main: Code (Text): было: int main(int argc, char* argv[]) { // some code return 0; } надо: int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) { // some code return 0; } ------ только заметил линкер у тебя _main не находит, значит ты создал проект Win32 console application для него соответственно надо не WinMain, а main
Four-F char* != long* См. определение макроса: Code (Text): (PCHAR)(base) + (ULONG)(offset) Компилятор умножает offset на размер указываемого типа, т.е. на единицу (sizeof(char) == 1), а должен умножить на 4! Поэтому DWORD_PTR нужно определить как посоветовал IceStudent.
Если определять как IceStudent, т.е. "typedef DWORD* DWORD_PTR;", то выдает след.ошибку: E:\test2\Cpp1.cpp(63) : error C2110: cannot add two pointers на строке: PIMAGE_NT_HEADERS pNTHeaders = MakePtr(PIMAGE_NT_HEADERS,hmodCaller,pDosHeader->e_lfanew); Макрос MakePtr, напомню, состоит из: #define MakePtr(cast, base, offset) (cast)((DWORD_PTR)(base) + (DWORD_PTR)(offset)) В общем, вопрос отктыт. Прога все равно не линкуется, хотя главная функция -- WinMain. Может попробуете у себе собрать - ну ничего не выходит. Уже весь измучился.
с этими исправлениями скомпилился нормально, только про атрибуты секции .text какой-то warning был: Code (Text): #include <windows.h> #include <tlhelp32.h> #include <imagehlp.h> #include "replace.h" #pragma comment(linker,"/MERGE:.rdata=.text") #pragma comment(linker,"/SECTION:.text,EWRX") #pragma comment(lib,"imagehlp.lib") #pragma comment(linker,"/BASE:0x29A00000") typedef DWORD *DWORD_PTR; #define MakePtr(cast, base, offset) (cast)((DWORD_PTR)(base) + (DWORD)(offset)) #define MakeRVAPtr(cast, base, rva) (cast)((DWORD_PTR)(base) + (DWORD)(RVAToOffset((DWORD)base, rva)))
Quantum, моё утверждение насчет приведения указателей к PCHAR касалось только так называемого случая "pointer arithmetic", когда производятся какие-то математические операции (сложение/вычитание) с указателем и указателем или указателем и смещением/длиной. Несколько пракрических примеров. 1. Макрос CONTAINING_RECORD (есть и SDK и d DDK). Указатель (адрес) приводится к PCHAR. Code (Text): // // Calculate the address of the base of the structure given its type, and an // address of a field within the structure. // #define CONTAINING_RECORD(address, type, field) ((type *)( \ (PCHAR)(address) - \ (ULONG_PTR)(&((type *)0)->field)))/code] 2. DDK, Раздел "Porting Issues Checklist", подраздел "Pointer Arithmetic": Be careful when computing buffer sizes. Consider the following: [code]len = ptr2 − ptr1 /* len could be greater than 2**32 */ Cast pointers to PCHAR for pointer arithmetic. Note If len is declared INT or ULONG, this will generate a compiler warning. Buffer sizes, even when computed correctly, may still exceed the capacity of ULONG. Т.е. в данном примере нужно сделать так: Code (Text): ULONG_PTR len; len = (PCHAR) ptr2 - (PCHAR) ptr1; 3. MSDN: "Beyond Windows XP: Get Ready Now for the Upcoming 64-Bit Version of Windows" Finally, for pointer arithmetic, cast pointers to PCHAR instead of ULONG. PCHAR compiles to either 32-bit or 64-bit depending on target bitness, while ULONG is always 32 bits and a cast to ULONG will therefore truncate half of your pointer. Code (Text): ptr = (PVOID)((PCHAR)ptr + pageSize); <font color="gray][ hasuhands1</font><!--color--><font color="gray]: В общем, вопрос отктыт. Прога все равно не линкуется, хотя главная функция -- WinMain. ]</font><!--color--> Тут масса вариантов. Можно так: Code (Text): #pragma comment(linker,"/ENTRY:main") int APIENTRY main(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { .... return 0; } Можно так: Code (Text): #pragma comment(linker,"/ENTRY:main") int main() { .... ExitProcess(0); return 0; } Можно даже так: Code (Text): #pragma comment(linker,"/ENTRY:main") void main() { .... }
Four-F Повторяю: указатель на long нельзя приводить к указателю на char, т.к. смещение перед сложением умножается на базовый тип указателя. Code (Text): char* p1 = (char*)0x404000; p1++; // p1 == 0x40400[b]1[/b] long* p2 = (long*)0x404000; p2++; // p2 == 0x40400[b]4[/b] Естественно. PCHAR - есть указатель, его размер зависит от платформы. ULONG - есть unsigned long int и по стандарту всегда имеет размер 32 бита. Приводить указатель к стандартному типу фиксированного размера нарушает портабельность. Это всё и так понятно. Если ptr2 >= ptr1, никаких проблем не возникнет. Компилятор не может знать заранее, что ptr2 >= ptr1. Поэтому результат лучше всего сразу кастовать на тип len: Code (Text): unsigned long len = (unsigned long)(ptr2 - ptr1); unsigned int len = (unsigned int)(ptr2 - ptr1); unsigned short len = (unsigned short)(ptr2 - ptr1); unsigned char len = (unsigned char)(ptr2 - ptr1); // *** Если я правильно понял, они советуют приводить результат к типу указателя (хоть void*). Но размер буфера никакой не указатель! Так что совет отклоняется.
Quantum Это причина скорее.. Вообще, это и частая ошибка при работе с указателями. Хочешь увеличить его на 1, а он был LPDWORD и получи +=4. С другой стороны, часто бывает необходима эта "указательная арифметика" - поэтому и приводят к PCHAR.
Quantum, хрен с ним Я всё равно точно знаю, что добавлять к указателям смещения/длину нужно так: (PVOID) ptr2 = (PVOID)((PCHAR) ptr1 + len); И как там ptr1 определён и на что он указывает - по-хрену. Вот волшебный макрос - тыщу лет пользуюсь для двиганья указателей: Code (Text): // // PVOID // AddToPtr ( // IN PVOID Pointer, // IN ULONG Increment // ); // #define AddToPtr(p,i) ((PVOID)((PCHAR)(p) + (i))) ЗЫ: и вообще мне некогда
Four-F В первом посте ты посоветовал заменить DWORD_PTR на PCHAR. Я обьяснил к чему приведёт такая замена (короче, код не будет работать). Теперь мы говорим о совсем разных вещах. У каждого свой стиль программирования, но я думаю, что у этого макроса больше минусов, чем плюсов. Правда, для обфускации сгодится Основной минус в том, что из названия нельзя точно определить что этот макрос делает. Можно подумать, что он учитывает тип указателя и, следовательно, неверно понять смысл кода.
<font color="gray][ Quantum</font><!--color--><font color="gray]: В первом посте ты посоветовал заменить DWORD_PTR на PCHAR. Я обьяснил к чему приведёт такая замена (короче, код не будет работать)... ]</font><!--color--> <font color="gray][ Quantum</font><!--color--><font color="gray]: Компилятор умножает offset на размер указываемого типа, т.е. на единицу (sizeof(char) == 1), а должен умножить на 4! ]</font><!--color--> Quantum, извини, но при всём моём уважении, ты просто не понимаешь о чём в данном случае идёт речь. Смысл приведения к PCHAR, в данном конкретном случае, как раз в том и состоит, чтобы идиот компилятор не умножал offset на размер указываемого типа. В данном случае мы точно знаем, что мы делаем - смещаем указатель на нужное нам число байт, а компилятор об этом не знает. Наша задача продвинуть указатель на какое-то значение и если мы не првиведём его к PCHAR, то как раз в этом случае код и не будет работать! В исходном коде топикстартера макрос MakePtr используется главным образом для перемещения по структурам PE-файла, например, для того, чтобы продвинуть указатель базы модуля к IMAGE_NT_HEADERS. Вот как это делает системная функция RtlImageNtHeader (код упрощён): Code (Text): PIMAGE_NT_HEADERS RtlImageNtHeader ( IN [b]PVOID Base[/b] ) { PIMAGE_NT_HEADERS NtHeaders = NULL; NtHeaders = (PIMAGE_NT_HEADERS)([b](PCHAR)Base[/b] + ((PIMAGE_DOS_HEADER)Base)->e_lfanew); return NtHeaders; } <font color="gray][ Quantum</font><!--color--><font color="gray]: У каждого свой стиль программирования, но я думаю, что у этого макроса больше минусов, чем плюсов... Основной минус в том, что из названия нельзя точно определить что этот макрос делает. Можно подумать, что он учитывает тип указателя и, следовательно, неверно понять смысл кода. ]</font><!--color--> Насчёт стиля - согласен, а вот насчёт имени... IMHO, имя - описательней некуда. Во всяком случае, я, точно знаю, что этот макрос делает И минусов, IMHO, у него вообще нет )) Его смысл как раз в том и состоит, чтобы похерить тип указателя и прибавить к нему именно то, что я просил, а не то, что компилятор посчитает правильным!
Я как-то без макросов обходился, хотя может тоже лишнего где нагородил %) Code (Text): int GetPEHeaderInfo(char* lpFileName, PE_HEADER_INFO* lpPEHeaderInfo) { int retValue = 0; HANDLE hFile = CreateFile(lpFileName, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); if(hFile != INVALID_HANDLE_VALUE) { HANDLE hMapFile = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL); if(hMapFile) { void* lpMapMemory = MapViewOfFile(hMapFile, FILE_MAP_READ, 0, 0, 0); if(lpMapMemory) { if((*(IMAGE_DOS_HEADER*)lpMapMemory).e_magic == IMAGE_DOS_SIGNATURE) { IMAGE_NT_HEADERS* lpNT_Headers = (IMAGE_NT_HEADERS*)((char*)lpMapMemory + (*(IMAGE_DOS_HEADER*)lpMapMemory).e_lfanew); if((*lpNT_Headers).Signature == IMAGE_NT_SIGNATURE) { (*lpPEHeaderInfo).EntryPoint = (*lpNT_Headers).OptionalHeader.AddressOfEntryPoint; (*lpPEHeaderInfo).BaseOfImage = (*lpNT_Headers).OptionalHeader.ImageBase; if(((*lpPEHeaderInfo).EntryPoint != 0) && ((*lpPEHeaderInfo).BaseOfImage != 0)) retValue++; } } UnmapViewOfFile(lpMapMemory); } CloseHandle(hMapFile); } CloseHandle(hFile); } return retValue; }
Code (Text): IMAGE_NT_HEADERS* lpNT_Headers = (IMAGE_NT_HEADERS*)([b](char*)[/b]lpMapMemory + (*(IMAGE_DOS_HEADER*)lpMapMemory).e_lfanew); Ну дык у тя тоже самое приведение к PCHAR, точнее у меня тоже самое приведение к char* Ибо typedef char CHAR; typedef CHAR *PCHAR;