// ------------------------------------------------------------- // ファイルイメージからメモリイメージを生成する関数 // 引数:pe(PEファイルのヘッダポインタ構造体のポインタ) // lpFileImage(ファイルイメージのポインタ) // dwMemSize (メモリイメージのサイズ) // 戻り値:成功時メモリイメージのポインタ、失敗時NULL // 備考:プロセスのメモリイメージを格納するためのメモリ領域を // VirtualAlloc関数にて確保するため、この関数を呼び出したら、そ // の後FreePEImage関数を呼び出しメモリを開放しなければならない。 // ------------------------------------------------------------- LPVOID LoadPEImage(PPE_HEADERS pe, LPVOID lpFileImage, DWORD dwMemSize) { // メモリを確保 LPVOID lpMemImage = (PTCHAR)VirtualAlloc( NULL, dwMemSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE); if(lpMemImage == NULL) return NULL; PTCHAR szInPtr = (PTCHAR)lpFileImage; PTCHAR szOutPtr = (PTCHAR)lpMemImage; // ヘッダをメモリイメージとしてコピー DWORD dwHeaderSize = pe->poh->SizeOfHeaders; for(int i=0; i < pe->pfh->NumberOfSections; i++){ if(pe->psh[i].PointerToRawData < dwHeaderSize) dwHeaderSize = pe->psh[i].PointerToRawData; } CopyMemory(szOutPtr, szInPtr, dwHeaderSize); // ポインタ移動 szOutPtr += GetAlignedSize( pe->poh->SizeOfHeaders, pe->poh->SectionAlignment); // 全セクションをメモリイメージとしてコピー for(int i=0; i < pe->pfh->NumberOfSections; i++){ // セクションサイズが0以下ならば無視 if(pe->psh[i].SizeOfRawData <= 0){ // もしVirtualSizeがあるなら更新 if(pe->psh[i].Misc.VirtualSize){ szInPtr += GetAlignedSize( pe->psh[i].Misc.VirtualSize, pe->poh->SectionAlignment); } continue; } // セクションの読み込みサイズを取得 DWORD dwToRead = pe->psh[i].SizeOfRawData; if(dwToRead > pe->psh[i].Misc.VirtualSize) dwToRead = pe->psh[i].Misc.VirtualSize; // 1セクションをメモリイメージとしてコピー szInPtr = (PTCHAR)lpFileImage + pe->psh[i].PointerToRawData; CopyMemory(szOutPtr, szInPtr, dwToRead); // ポインタ移動 szOutPtr += GetAlignedSize( pe->psh[i].Misc.VirtualSize, pe->poh->SectionAlignment); } // メモリポインタを返す return lpMemImage; }
// ------------------------------------------------------------- // メモリイメージのサイズを計算する関数 // 引数:pe(PEファイルのヘッダポインタ構造体のポインタ) // 戻り値:メモリイメージのサイズ // ------------------------------------------------------------- DWORD TotalNewImageSize(PPE_HEADERS pe) { // ヘッダのサイズを代入 DWORD dwRet = GetAlignedSize( pe->poh->SizeOfHeaders, pe->poh->SectionAlignment); // セクションごとのサイズを加算 for(int i=0; i < pe->pfh->NumberOfSections; i++){ if( ! pe->psh[i].Misc.VirtualSize) continue; dwRet += GetAlignedSize( pe->psh[i].Misc.VirtualSize, pe->poh->SectionAlignment); } // PEファイルのイメージサイズを返す return dwRet; }
// 计算加载pe并对齐需要占用多少内存 // 未直接使用OptionalHeader.SizeOfImage作为结果是因为据说有的编译器生成的exe这个值会填0 unsigned long CExeMemory::CalcTotalImageSize(PIMAGE_DOS_HEADER MzH, unsigned long FileLen, PIMAGE_NT_HEADERS peH, PIMAGE_SECTION_HEADERS peSecH) { unsigned long res; // 计算pe头的大小 res = GetAlignedSize( peH->OptionalHeader.SizeOfHeaders , peH->OptionalHeader.SectionAlignment ); // 计算所有节的大小 for( int i = 0; i < peH->FileHeader.NumberOfSections; ++i) { // 超出文件范围 if(peSecH[i]->PointerToRawData + peSecH[i]->SizeOfRawData > FileLen) return 0; else if(peSecH[i]->VirtualAddress)//计算对齐后某节的大小 { if(peSecH[i]->Misc.VirtualSize) { res = GetAlignedSize( peSecH[i]->VirtualAddress + peSecH[i]->Misc.VirtualSize , peH->OptionalHeader.SectionAlignment ); } else { res = GetAlignedSize( peSecH[i]->VirtualAddress + peSecH[i]->SizeOfRawData , peH->OptionalHeader.SectionAlignment ); } } else if( peSecH[i]->Misc.VirtualSize < peSecH[i]->SizeOfRawData ) { res += GetAlignedSize( peSecH[i]->SizeOfRawData , peH->OptionalHeader.SectionAlignment ); } else { res += GetAlignedSize( peSecH[i]->Misc.VirtualSize , peH->OptionalHeader.SectionAlignment ); }// if_else }// for return res; }
/** @brief Receive message from the server @param size - return size of data @param decrypt - if TRUE, then decrypt received data by session key @param control - return control character @return data (you MUST free memory after use) */ byte *tcpReceiveMessage(int Handle, uint32 *size, byte *control, uint32 TimeoutMsec) { StreamMethod Method = smRecvSend; byte *data; int ret = 0; byte cc = 0; byte LengthField[MAXLENGTHFIELDSIZE]; byte LengthFieldSize; uint32 AlignedSize; byte AttempsCount = 1; byte MaxAttempsCount = 5; lblWaitAgain: *size = 0; *control = 0; data = NULL; sleepms(100); ret = recvByte(Handle, Method, &cc, 0/*Timeout*/); //printf"recvByte: %d. byte %d\n", ret, cc); if (ret > 0) { *control = cc; switch (cc) { case pccSTX: *size = ReceiveLengthField(Handle, Method, LengthField, &LengthFieldSize, TimeoutMsec); // получаем размер данных if (*size != 0xFFFFFFFF) { AlignedSize = GetAlignedSize(*size); data = malloc(AlignedSize); // allocate data ret = recvBuffer(Handle, Method, data, AlignedSize, TimeoutMsec); #ifdef TCP_DEBUG // PrintHEX(data, *size); #endif //printf"comRecvBufLarge: %d\n", ret); if (ret > 0) { // ok, we have a data - calc CRC uint32 CRCBufferSize = LengthFieldSize + AlignedSize + 1; // datasize + data + ETX byte *CRCBuffer = malloc(CRCBufferSize); memcpy(CRCBuffer, LengthField, LengthFieldSize); // copy length field to checkbuffer memcpy(CRCBuffer+LengthFieldSize, data, AlignedSize); // copy data from checkbuffer CRCBuffer[CRCBufferSize - 1] = pccETX; // last character = ETX uint64 CalculatedCRC = crcCalculate(CRCBuffer, CRCBufferSize); free(CRCBuffer); CRCBuffer = NULL; ret = recvByte(Handle, Method, &cc, TimeoutMsec); // receive ETX character //printf"comRecv: %d. byte %d\n", ret, cc); if (ret > 0 && cc == pccETX) { byte crcfield[crcGetFieldSize(CRCBufferSize)]; ret = recvBuffer(Handle, Method, crcfield, sizeof(crcfield), TimeoutMsec); // get size uint64 ReceivedCRC = crcExtract(crcfield, sizeof(crcfield)); //printf"comRecvBuf: %d\n", ret); if (ret > 0) { if (ReceivedCRC == CalculatedCRC) // check the data ret = sendByte(Handle, Method, pccACK); // good!!! else { if (AttempsCount <= MaxAttempsCount) { AttempsCount++; ret = sendByte(Handle, Method, pccNAK); // and go to wait this packet again goto lblWaitAgain; } else { free(data); data = NULL; } } } else { free(data); data = NULL; } } else { free(data); data = NULL; } } else { free(data); data = NULL; } } break; case pccEOT: // query close connection data = NULL; break; case pccBEL: sendByte(Handle, Method, pccBEL); goto lblWaitAgain; default: data = NULL; break; } } else { *control = 0; data = NULL; } /*if (data) cphDecrypt(data, data, PCSessionKey, AlignedSize, ToServer); // decipher received data*/ return data; }
/** @brief Send message to the server (PC or Retail system) @param size - return size of data @param decrypt - if TRUE, then decrypt received data by session key @param control - return control character @return TRUE if OK, or error code */ Bool tcpSendMessage(int Handle, byte *Data, uint32 DataSize, uint32 TimeoutMSec) { StreamMethod Method = smRecvSend; int ret; Bool result = FALSE; uint32 size = DataSize; uint32 AlignedSize = GetAlignedSize(size); byte LengthField[MAXLENGTHFIELDSIZE]; byte LengthFieldSize; tlvMakeLengthField(size, LengthField, &LengthFieldSize); byte MaxAttempsCount = 5; byte ack; tBuffer sendbuf; byte DataToSend[AlignedSize + MAXLENGTHFIELDSIZE + 1 + MAXCRCBUFFERSIZE]; // + max data size buffer, ETX, max CRC buffer bufInit(&sendbuf, DataToSend, sizeof(DataToSend)); // init buffer for writing (and clear of DataToSend) bufApp(&sendbuf, LengthField, LengthFieldSize); memcpy(DataToSend + sendbuf.pos, Data, DataSize); // просто копирование, без шифрования sendbuf.pos += AlignedSize; // DataToSend уже лежит в буфере на отправку bufAppByte(&sendbuf, pccETX); // append ETX to buffer byte CRCBuffer[MAXCRCBUFFERSIZE]; byte CRCBufferSize = crcMakeField(sendbuf.ptr, (word)sendbuf.pos, CRCBuffer); bufApp(&sendbuf, CRCBuffer, CRCBufferSize); /* printf("CRC Buffer: "); PrintHEX(CRCBuffer, CRCBufferSize);*/ byte AttempsCount = 1; lblSendAgain: ret = sendByte(Handle, Method, pccSTX); // send control char "start of packet" if (ret > 0) { ret = sendBuffer(Handle, Method, bufPtr(&sendbuf), bufLen(&sendbuf)); // send packet if (ret == bufLen(&sendbuf)) { // and wait for acknowledgment lblWaitAskAgain: ack = 0; ret = recvByte(Handle, Method, &ack, TimeoutMSec); if (ret > 0) { switch (ack) { case pccACK: // good result = TRUE; break; case pccBEL: // please, wait sendByte(Handle, Method, pccBEL); goto lblWaitAskAgain; case pccNAK: // send packet again if (AttempsCount <= MaxAttempsCount) { AttempsCount++; goto lblSendAgain; } else result = FALSE; break; default: // unknown state result = FALSE; break; } } else result = FALSE; } else result = FALSE; } else result = FALSE; //ptarr = memFree(ptarr); return result; }
// 加载pe到内存并对齐所有节 BOOL CExeMemory::AlignPEToMem( void *Buf, long Len, PIMAGE_NT_HEADERS &peH, PIMAGE_SECTION_HEADERS &peSecH, void *&Mem, unsigned long &ImageSize) { PIMAGE_DOS_HEADER SrcMz;// DOS头 PIMAGE_NT_HEADERS SrcPeH;// PE头 PIMAGE_SECTION_HEADERS SrcPeSecH;// 节表 SrcMz = (PIMAGE_DOS_HEADER)Buf; if( Len < sizeof(IMAGE_DOS_HEADER) ) return FALSE; if( SrcMz->e_magic != IMAGE_DOS_SIGNATURE ) return FALSE; if( Len < SrcMz->e_lfanew + (long)sizeof(IMAGE_NT_HEADERS) ) return FALSE; SrcPeH = (PIMAGE_NT_HEADERS)((int)SrcMz + SrcMz->e_lfanew); if( SrcPeH->Signature != IMAGE_NT_SIGNATURE ) return FALSE; if( (SrcPeH->FileHeader.Characteristics & IMAGE_FILE_DLL) || (SrcPeH->FileHeader.Characteristics & IMAGE_FILE_EXECUTABLE_IMAGE == 0) || (SrcPeH->FileHeader.SizeOfOptionalHeader != sizeof(IMAGE_OPTIONAL_HEADER)) ) { return FALSE; } SrcPeSecH = (PIMAGE_SECTION_HEADERS)((int)SrcPeH + sizeof(IMAGE_NT_HEADERS)); ImageSize = CalcTotalImageSize( SrcMz, Len, SrcPeH, SrcPeSecH); if( ImageSize == 0 ) return FALSE; Mem = VirtualAlloc( NULL, ImageSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE); // 分配内存 if( Mem != NULL ) { // 计算需要复制的PE头字节数 unsigned long l = SrcPeH->OptionalHeader.SizeOfHeaders; for( int i = 0; i < SrcPeH->FileHeader.NumberOfSections; ++i) { if( (SrcPeSecH[i]->PointerToRawData) && (SrcPeSecH[i]->PointerToRawData < l) ) { l = SrcPeSecH[i]->PointerToRawData; } } memmove( Mem, SrcMz, l); peH = (PIMAGE_NT_HEADERS)((int)Mem + ((PIMAGE_DOS_HEADER)Mem)->e_lfanew); peSecH = (PIMAGE_SECTION_HEADERS)((int)peH + sizeof(IMAGE_NT_HEADERS)); void *Pt = (void *)((unsigned long)Mem + GetAlignedSize( peH->OptionalHeader.SizeOfHeaders , peH->OptionalHeader.SectionAlignment) ); for( int i = 0; i < peH->FileHeader.NumberOfSections; ++i) { // 定位该节在内存中的位置 if(peSecH[i]->VirtualAddress) Pt = (void *)((unsigned long)Mem + peSecH[i]->VirtualAddress); if(peSecH[i]->SizeOfRawData) { // 复制数据到内存 memmove(Pt, (const void *)((unsigned long)(SrcMz) + peSecH[i]->PointerToRawData), peSecH[i]->SizeOfRawData); if(peSecH[i]->Misc.VirtualSize < peSecH[i]->SizeOfRawData) Pt = (void *)((unsigned long)Pt + GetAlignedSize(peSecH[i]->SizeOfRawData, peH->OptionalHeader.SectionAlignment)); else // pt 定位到下一节开始位置 Pt = (void *)((unsigned long)Pt + GetAlignedSize(peSecH[i]->Misc.VirtualSize, peH->OptionalHeader.SectionAlignment)); } else { Pt = (void *)((unsigned long)Pt + GetAlignedSize(peSecH[i]->Misc.VirtualSize, peH->OptionalHeader.SectionAlignment)); } } } return TRUE; }