C -> Delphi

Hi!
I'm bothering you again with some C to Delphi translation... I'm willing to increase the points if I get a good translation!

Thanks in advance!

///////////////////////////// code /////////////////////////////////

ULONG __fastcall GetSizeOfImage(
    IN PVOID pImageBase
    )
{
    // get DOS header
    IMAGE_DOS_HEADER * pDosHeader = (IMAGE_DOS_HEADER *)pImageBase;

    // find an offset to the main PE header ...
    IMAGE_FILE_HEADER * pFileHeader =
        (IMAGE_FILE_HEADER *)(((LPBYTE)pImageBase) +
                      pDosHeader->e_lfanew +
                      sizeof(IMAGE_NT_SIGNATURE));

    // ... and optional PE header
    IMAGE_OPTIONAL_HEADER * pOptHeader =
        (IMAGE_OPTIONAL_HEADER *)(((LPBYTE)pFileHeader) +
                      IMAGE_SIZEOF_FILE_HEADER);

    // calculate the size
    ULONG nSizeOfImage = pOptHeader->SizeOfHeaders;

    IMAGE_SECTION_HEADER * pSecHeader =
        (IMAGE_SECTION_HEADER *)(((LPBYTE)pOptHeader) +
                     pFileHeader->SizeOfOptionalHeader);

    // sum size of all image sections; this will result in the image
    // size
    for (int i = 0; i < pFileHeader->NumberOfSections; i++, pSecHeader++)
        nSizeOfImage += pSecHeader->SizeOfRawData;

    // return size of the executable
    return nSizeOfImage;
}

IMAGE_SECTION_HEADER* GetSectionHeader(IN PVOID pImageBase)
{
    // get DOS header
    IMAGE_DOS_HEADER * pDosHeader = (IMAGE_DOS_HEADER *)pImageBase;

    // find an offset to the main PE header ...
    IMAGE_FILE_HEADER * pFileHeader =
        (IMAGE_FILE_HEADER *)(((LPBYTE)pImageBase) +
                      pDosHeader->e_lfanew +
                      sizeof(IMAGE_NT_SIGNATURE));

    // ... and optional PE header
    IMAGE_OPTIONAL_HEADER * pOptHeader =
        (IMAGE_OPTIONAL_HEADER *)(((LPBYTE)pFileHeader) +
                      IMAGE_SIZEOF_FILE_HEADER);

    // calculate the size
    ULONG nSizeOfImage = pOptHeader->SizeOfHeaders;

    IMAGE_SECTION_HEADER * pSecHeader =
        (IMAGE_SECTION_HEADER *)(((LPBYTE)pOptHeader) +
                     pFileHeader->SizeOfOptionalHeader);
      return pSecHeader;
}


PIMAGE_SECTION_HEADER FindLastVirtualSection(DWORD* pImageBase)
{
    // get DOS header
    IMAGE_DOS_HEADER * pDosHeader = (IMAGE_DOS_HEADER *)pImageBase;
      
      // get NT header
    IMAGE_NT_HEADERS * pNtHeaders = (IMAGE_NT_HEADERS*)((DWORD)pImageBase+pDosHeader->e_lfanew);

      // find an offset to the main PE header ...
    IMAGE_FILE_HEADER * pFileHeader =
        (IMAGE_FILE_HEADER *)(((LPBYTE)pImageBase) +
                      pDosHeader->e_lfanew +
                      sizeof(IMAGE_NT_SIGNATURE));

    // ... and optional PE header
    IMAGE_OPTIONAL_HEADER * pOptHeader =
        (IMAGE_OPTIONAL_HEADER *)(((LPBYTE)pFileHeader) +
                      IMAGE_SIZEOF_FILE_HEADER);

    IMAGE_SECTION_HEADER * sectionHeader =
        (IMAGE_SECTION_HEADER *)(((LPBYTE)pOptHeader) +
                     pFileHeader->SizeOfOptionalHeader);

      DWORD newSectionOffset;
      DWORD SectionNum = pNtHeaders->FileHeader.NumberOfSections;

      DWORD currentMaxVA = 0;
      int pos = 0;

      IMAGE_SECTION_HEADER* tempHeader = sectionHeader;
      DWORD headerSize = sizeof(IMAGE_SECTION_HEADER);
      for(int i = 0; i < SectionNum; i++)
      {
            if((DWORD)(tempHeader->VirtualAddress) > currentMaxVA)
            {
                  currentMaxVA = (DWORD)(tempHeader->VirtualAddress);
                  pos = i;
            }
            tempHeader = (IMAGE_SECTION_HEADER*)((DWORD)tempHeader + headerSize);
      }

      IMAGE_SECTION_HEADER* lastSectionHeader = (IMAGE_SECTION_HEADER*)((DWORD)sectionHeader + pos*sizeof(IMAGE_SECTION_HEADER));
      return lastSectionHeader;
}

PIMAGE_SECTION_HEADER FindLastPhysicalSection(DWORD* pImageBase)
{
    // get DOS header
    IMAGE_DOS_HEADER * pDosHeader = (IMAGE_DOS_HEADER *)pImageBase;
      
      // get NT header
    IMAGE_NT_HEADERS * pNtHeaders = (IMAGE_NT_HEADERS*)((DWORD)pImageBase+pDosHeader->e_lfanew);

      // find an offset to the main PE header ...
    IMAGE_FILE_HEADER * pFileHeader =
        (IMAGE_FILE_HEADER *)(((LPBYTE)pImageBase) +
                      pDosHeader->e_lfanew +
                      sizeof(IMAGE_NT_SIGNATURE));

    // ... and optional PE header
    IMAGE_OPTIONAL_HEADER * pOptHeader =
        (IMAGE_OPTIONAL_HEADER *)(((LPBYTE)pFileHeader) +
                      IMAGE_SIZEOF_FILE_HEADER);

    IMAGE_SECTION_HEADER * sectionHeader =
        (IMAGE_SECTION_HEADER *)(((LPBYTE)pOptHeader) +
                     pFileHeader->SizeOfOptionalHeader);

      DWORD newSectionOffset;
      DWORD SectionNum = pNtHeaders->FileHeader.NumberOfSections;

      DWORD currentMaxPA = 0;
      int pos = 0;

      IMAGE_SECTION_HEADER* tempHeader = sectionHeader;
      DWORD headerSize = sizeof(IMAGE_SECTION_HEADER);
      for(int i = 0; i < SectionNum; i++)
      {
            if((DWORD)(tempHeader->PointerToRawData) > currentMaxPA)
            {
                  currentMaxPA = (DWORD)(tempHeader->PointerToRawData);
                  pos = i;
            }
            tempHeader = (IMAGE_SECTION_HEADER*)((DWORD)tempHeader + headerSize);
      }

      IMAGE_SECTION_HEADER* lastSectionHeader = (IMAGE_SECTION_HEADER*)((DWORD)sectionHeader + pos*sizeof(IMAGE_SECTION_HEADER));
      return lastSectionHeader;
}

PIMAGE_SECTION_HEADER FindFirstSection(DWORD* pImageBase)
{
    // get DOS header
    IMAGE_DOS_HEADER * pDosHeader = (IMAGE_DOS_HEADER *)pImageBase;
      
      // get NT header
    IMAGE_NT_HEADERS * pNtHeaders = (IMAGE_NT_HEADERS*)((DWORD)pImageBase+pDosHeader->e_lfanew);

      // find an offset to the main PE header ...
    IMAGE_FILE_HEADER * pFileHeader =
        (IMAGE_FILE_HEADER *)(((LPBYTE)pImageBase) +
                      pDosHeader->e_lfanew +
                      sizeof(IMAGE_NT_SIGNATURE));

    // ... and optional PE header
    IMAGE_OPTIONAL_HEADER * pOptHeader =
        (IMAGE_OPTIONAL_HEADER *)(((LPBYTE)pFileHeader) +
                      IMAGE_SIZEOF_FILE_HEADER);

    IMAGE_SECTION_HEADER * sectionHeader =
        (IMAGE_SECTION_HEADER *)(((LPBYTE)pOptHeader) +
                     pFileHeader->SizeOfOptionalHeader);

      return sectionHeader;
}


PIMAGE_SECTION_HEADER FindNextSection(DWORD* pImageBase, PIMAGE_SECTION_HEADER currentSection)
{
    // get DOS header
    IMAGE_DOS_HEADER * pDosHeader = (IMAGE_DOS_HEADER *)pImageBase;
      
      // get NT header
    IMAGE_NT_HEADERS * pNtHeaders = (IMAGE_NT_HEADERS*)((DWORD)pImageBase+pDosHeader->e_lfanew);

      // find an offset to the main PE header ...
    IMAGE_FILE_HEADER * pFileHeader =
        (IMAGE_FILE_HEADER *)(((LPBYTE)pImageBase) +
                      pDosHeader->e_lfanew +
                      sizeof(IMAGE_NT_SIGNATURE));

    // ... and optional PE header
    IMAGE_OPTIONAL_HEADER * pOptHeader =
        (IMAGE_OPTIONAL_HEADER *)(((LPBYTE)pFileHeader) +
                      IMAGE_SIZEOF_FILE_HEADER);

    IMAGE_SECTION_HEADER * sectionHeader =
        (IMAGE_SECTION_HEADER *)(((LPBYTE)pOptHeader) +
                     pFileHeader->SizeOfOptionalHeader);

      DWORD newSectionOffset;
      DWORD SectionNum = pNtHeaders->FileHeader.NumberOfSections;

      if(SectionNum <= 1) return NULL;

      IMAGE_SECTION_HEADER* prevHeader = sectionHeader;
      IMAGE_SECTION_HEADER* currHeader = (IMAGE_SECTION_HEADER*)((DWORD)sectionHeader + sizeof(IMAGE_SECTION_HEADER));
      DWORD headerSize = sizeof(IMAGE_SECTION_HEADER);
      for(int i = 0; i < SectionNum - 1; i++)
      {
            if(prevHeader == currentSection) return currHeader;
            prevHeader = currHeader;
            currHeader = (IMAGE_SECTION_HEADER*)((DWORD)currHeader + sizeof(IMAGE_SECTION_HEADER));
      }

      return NULL;
}

PIMAGE_SECTION_HEADER FindSection(DWORD* pImageBase, DWORD sectionbase)
{
    // get DOS header
    IMAGE_DOS_HEADER * pDosHeader = (IMAGE_DOS_HEADER *)pImageBase;
      
      // get NT header
    IMAGE_NT_HEADERS * pNtHeaders = (IMAGE_NT_HEADERS*)((DWORD)pImageBase+pDosHeader->e_lfanew);

      // find an offset to the main PE header ...
    IMAGE_FILE_HEADER * pFileHeader =
        (IMAGE_FILE_HEADER *)(((LPBYTE)pImageBase) +
                      pDosHeader->e_lfanew +
                      sizeof(IMAGE_NT_SIGNATURE));

    // ... and optional PE header
    IMAGE_OPTIONAL_HEADER * pOptHeader =
        (IMAGE_OPTIONAL_HEADER *)(((LPBYTE)pFileHeader) +
                      IMAGE_SIZEOF_FILE_HEADER);

    IMAGE_SECTION_HEADER * sectionHeader =
        (IMAGE_SECTION_HEADER *)(((LPBYTE)pOptHeader) +
                     pFileHeader->SizeOfOptionalHeader);

      DWORD newSectionOffset;
      DWORD SectionNum = pNtHeaders->FileHeader.NumberOfSections;

      DWORD currentMaxVA = 0;
      int pos = 0;

      IMAGE_SECTION_HEADER* tempHeader = sectionHeader;
      DWORD headerSize = sizeof(IMAGE_SECTION_HEADER);
      for(int i = 0; i < SectionNum; i++)
      {
            if(tempHeader->VirtualAddress == sectionbase)
            {
                  return tempHeader;
            }
            tempHeader = (IMAGE_SECTION_HEADER*)((DWORD)tempHeader + headerSize);
      }

      return NULL;
}

void MakeAllSectionsWritable(DWORD* pImageBase)
{
    // get DOS header
    IMAGE_DOS_HEADER * pDosHeader = (IMAGE_DOS_HEADER *)pImageBase;
      
      // get NT header
    IMAGE_NT_HEADERS * pNtHeaders = (IMAGE_NT_HEADERS*)((DWORD)pImageBase+pDosHeader->e_lfanew);

      // find an offset to the main PE header ...
    IMAGE_FILE_HEADER * pFileHeader =
        (IMAGE_FILE_HEADER *)(((LPBYTE)pImageBase) +
                      pDosHeader->e_lfanew +
                      sizeof(IMAGE_NT_SIGNATURE));

    // ... and optional PE header
    IMAGE_OPTIONAL_HEADER * pOptHeader =
        (IMAGE_OPTIONAL_HEADER *)(((LPBYTE)pFileHeader) +
                      IMAGE_SIZEOF_FILE_HEADER);

    IMAGE_SECTION_HEADER * sectionHeader =
        (IMAGE_SECTION_HEADER *)(((LPBYTE)pOptHeader) +
                     pFileHeader->SizeOfOptionalHeader);

      DWORD newSectionOffset;
      DWORD SectionNum = pNtHeaders->FileHeader.NumberOfSections;

      DWORD currentMaxVA = 0;
      int pos = 0;

      IMAGE_SECTION_HEADER* tempHeader = sectionHeader;
      DWORD headerSize = sizeof(IMAGE_SECTION_HEADER);
      for(int i = 0; i < SectionNum; i++)
      {
            tempHeader->Characteristics |= IMAGE_SCN_MEM_WRITE;
            tempHeader = (IMAGE_SECTION_HEADER*)((DWORD)tempHeader + headerSize);
      }

      return ;
}

PIMAGE_SECTION_HEADER AddSection(DWORD* pImageBase, DWORD codeVirtualStart, DWORD codeSize)
{
    // get DOS header
    IMAGE_DOS_HEADER * pDosHeader = (IMAGE_DOS_HEADER *)pImageBase;
      
      // get NT header
    IMAGE_NT_HEADERS * pNtHeaders = (IMAGE_NT_HEADERS*)((DWORD)pImageBase+pDosHeader->e_lfanew);

      // find an offset to the main PE header ...
    IMAGE_FILE_HEADER * pFileHeader =
        (IMAGE_FILE_HEADER *)(((LPBYTE)pImageBase) +
                      pDosHeader->e_lfanew +
                      sizeof(IMAGE_NT_SIGNATURE));

    // ... and optional PE header
    IMAGE_OPTIONAL_HEADER * pOptHeader =
        (IMAGE_OPTIONAL_HEADER *)(((LPBYTE)pFileHeader) +
                      IMAGE_SIZEOF_FILE_HEADER);

    IMAGE_SECTION_HEADER * sectionHeader =
        (IMAGE_SECTION_HEADER *)(((LPBYTE)pOptHeader) +
                     pFileHeader->SizeOfOptionalHeader);

      DWORD newSectionOffset;
      DWORD SectionNum = pNtHeaders->FileHeader.NumberOfSections;

      newSectionOffset = (DWORD)sectionHeader
            +pNtHeaders->FileHeader.NumberOfSections*sizeof(IMAGE_SECTION_HEADER) - (DWORD)pImageBase;

      // check whether there's room for a new section
      if(pNtHeaders->OptionalHeader.SizeOfHeaders<(newSectionOffset+sizeof(IMAGE_SECTION_HEADER)))
      {
            return NULL;
      }

      // increase SizeOf

      // create a new section

      IMAGE_SECTION_HEADER* newsection = (IMAGE_SECTION_HEADER*)((DWORD)pImageBase + newSectionOffset);

      // start to build the new section
      DWORD n = sizeof(IMAGE_SECTION_HEADER);
      CopyMemory(newsection,
                     (IMAGE_SECTION_HEADER*)((DWORD)newsection - n),
                     sizeof(IMAGE_SECTION_HEADER));

      // VirtualAddress...

      // update the PE header
      pNtHeaders->FileHeader.NumberOfSections++;
      // newsection -> will be returned
      return (PIMAGE_SECTION_HEADER)newsection;
}

DWORD EncryptSection(IMAGE_SECTION_HEADER* codeSection, DWORD* imageBase, DWORD seed)
{
      DWORD rawCodePosition = codeSection->PointerToRawData;

      DWORD virtualCodeSize = codeSection->SizeOfRawData;//->Misc.VirtualSize;

      DWORD startpos = (DWORD)imageBase + (DWORD)rawCodePosition;
      
      if(stricmp((char*)codeSection->Name, ".rsrc") == 0) startpos = startpos + 0x11;

      DWORD endpos = startpos + virtualCodeSize;

      // unprotect code
      BOOL diditwork = VirtualProtect((void*)startpos, virtualCodeSize, PAGE_READWRITE, NULL);
      DWORD x = GetLastError();

      _asm
      {
            sub EAX, EAX;
            mov EAX, seed;

            mov EBX, startpos;
            mov EDX, endpos;
StartLoop:
            CMP EBX, EDX; // when these are the same, stop
            JZ StopLooping
                  mov CL, BYTE PTR [EBX] // get value at address EBX
                  add CL, AL;      // crypt it
                  mov BYTE PTR [EBX], CL  // put decrypted value back in right place
                  inc EBX;
                  call GenerateRandomNumber; // get next LCG value
            jmp StartLoop;
StopLooping:
            mov seed, EAX;
      }
      return seed;
}

///////////////////////// code /////////////////////////////

Best Regards,
      Cosmin.
LVL 4
anorganixAsked:
Who is Participating?
 
Russell LibbyConnect With a Mentor Software Engineer, Advisory Commented:
Cosmin,

Here's the code, tested and checked (I dont recommend running the encryption over ALL the executing code's data, lol). The only missing piece is the random number generator call.

Russell

---

unit PEUtils;
////////////////////////////////////////////////////////////////////////////////
//
//   Unit        :  PEUtils
//   Date        :  06.07.2006
//   Description :  PE utility functions
//
////////////////////////////////////////////////////////////////////////////////
interface

////////////////////////////////////////////////////////////////////////////////
//   Include units
////////////////////////////////////////////////////////////////////////////////
uses
  Windows, SysUtils;

////////////////////////////////////////////////////////////////////////////////
//   Utility functions
////////////////////////////////////////////////////////////////////////////////
function   GetSizeOfImage(pImageBase: Pointer): ULONG;
function   GetSectionHeader(pImageBase: Pointer): PImageSectionHeader;
function   FindLastVirtualSection(pImageBase: Pointer): PImageSectionHeader;
function   FindLastPhysicalSection(pImageBase: Pointer): PImageSectionHeader;
function   FindFirstSection(pImageBase: Pointer): PImageSectionHeader;
function   FindNextSection(pImageBase: Pointer; CurrentSection: PImageSectionHeader): PImageSectionHeader;
function   FindSection(pImageBase: Pointer; SectionBase: DWORD): PImageSectionHeader;
procedure  MakeAllSectionsWritable(pImageBase: Pointer);
function   AddSection(pImageBase: Pointer; CodeVirtualStart, CodeSize: DWORD): PImageSectionHeader;
function   EncryptSection(CodeSection: PImageSectionHeader; pImageBase: Pointer; Seed: DWORD): DWORD;

implementation

function CalcOffset(Pointers: Array of Pointer): Pointer;
var  dwIndex:          Integer;
begin

  // Default result
  result:=nil;

  // Calculate the offset by adding the pointers
  for dwIndex:=0 to High(Pointers) do Inc(PChar(result), Integer(Pointers[dwIndex]));

end;

function GetSizeOfImage(pImageBase: Pointer): ULONG;
var  pDosHeader:       PImageDosHeader;
     pFileHeader:      PImageFileHeader;
     pOptHeader:       PImageOptionalHeader;
     pSecHeader:       PImageSectionHeader;
     pNtSignature:     PLongWord;
     nSizeOfImage:     ULONG;
     dwIndex:          Integer;
begin

  // Get DOS header
  pDosHeader:=pImageBase;

  // Get PE header location
  pNtSignature:=PLongWord(CalcOffset([pImageBase, Pointer(pDosHeader._lfanew)]));

  // Check PE signature
  if (pNtSignature^ = IMAGE_NT_SIGNATURE) then
  begin
     // Push past the signature
     Inc(PChar(pNtSignature), SizeOf(LongWord));
     // Find an offset to the main PE header
     pFileHeader:=PImageFileHeader(pNtSignature);
     // Get optional PE header
     pOptHeader:=PImageOptionalHeader(CalcOffset([pFileHeader, Pointer(IMAGE_SIZEOF_FILE_HEADER)]));
     // Calculate the size
     nSizeOfImage:=pOptHeader^.SizeOfHeaders;
     // Get first section header
     pSecHeader:=PImageSectionHeader(CalcOffset([pOptHeader, Pointer(pFileHeader^.SizeOfOptionalHeader)]));
     // Sum size of all image sections; this will result in the image size
     for dwIndex:=0 to Pred(pFileHeader^.NumberOfSections) do
     begin
        // Add the raw data size
        Inc(nSizeOfImage, pSecHeader^.SizeOfRawData);
        // Next section
        pSecHeader:=PImageSectionHeader(CalcOffset([pSecHeader, Pointer(IMAGE_SIZEOF_SECTION_HEADER)]));
     end;
     // Return size of the executable
     result:=nSizeOfImage;
  end
  else
     // Not a valid signature
     result:=0;

end;

function GetSectionHeader(pImageBase: Pointer): PImageSectionHeader;
var  pDosHeader:       PImageDosHeader;
     pFileHeader:      PImageFileHeader;
     pOptHeader:       PImageOptionalHeader;
     pNtSignature:     PLongWord;
begin

  // Get DOS header
  pDosHeader:=pImageBase;

  // Get PE header location
  pNtSignature:=PLongWord(CalcOffset([pImageBase, Pointer(pDosHeader._lfanew)]));

  // Check PE signature
  if (pNtSignature^ = IMAGE_NT_SIGNATURE) then
  begin
     // Push past the signature
     Inc(PChar(pNtSignature), SizeOf(LongWord));
     // Find an offset to the main PE header
     pFileHeader:=PImageFileHeader(pNtSignature);
     // Get optional PE header
     pOptHeader:=PImageOptionalHeader(CalcOffset([pFileHeader, Pointer(IMAGE_SIZEOF_FILE_HEADER)]));
     // Get first section header
     result:=PImageSectionHeader(CalcOffset([pOptHeader, Pointer(pFileHeader^.SizeOfOptionalHeader)]));
  end
  else
     // Not a valid image
     result:=nil;

end;

function FindLastVirtualSection(pImageBase: Pointer): PImageSectionHeader;
var  pDosHeader:       PImageDosHeader;
     pNtHeaders:       PImageNtHeaders;
     pFileHeader:      PImageFileHeader;
     pOptHeader:       PImageOptionalHeader;
     pSecHeader:       PImageSectionHeader;
     pTempHeader:      PImageSectionHeader;
     pNtSignature:     PLongWord;
     dwCurrentMaxVA:   DWORD;
     dwPos:            Integer;
     dwIndex:          Integer;
begin

  // Get DOS header
  pDosHeader:=pImageBase;

  // Get PE header location
  pNtSignature:=PLongWord(CalcOffset([pImageBase, Pointer(pDosHeader._lfanew)]));

  // Check PE signature
  if (pNtSignature^ = IMAGE_NT_SIGNATURE) then
  begin
     // Save the NT header
     pNtHeaders:=PImageNtHeaders(pNtSignature);
     // Push past the signature
     Inc(PChar(pNtSignature), SizeOf(LongWord));
     // Find an offset to the main PE header
     pFileHeader:=PImageFileHeader(pNtSignature);
     // Get optional PE header
     pOptHeader:=PImageOptionalHeader(CalcOffset([pFileHeader, Pointer(IMAGE_SIZEOF_FILE_HEADER)]));
     // Get first section header
     pSecHeader:=PImageSectionHeader(CalcOffset([pOptHeader, Pointer(pFileHeader^.SizeOfOptionalHeader)]));
     // Save first section header
     dwPos:=0;
     dwCurrentMaxVA:=0;
     pTempHeader:=pSecHeader;
     // Walk the sections
     for dwIndex:=0 to Pred(pNtHeaders^.FileHeader.NumberOfSections) do
     begin
        // Check virtual address
        if (pTempHeader^.VirtualAddress > dwCurrentMaxVA) then
        begin
           // Update current max VA
           dwCurrentMaxVA:=pTempHeader^.VirtualAddress;
           // Save index
           dwPos:=dwIndex;
        end;
        // Get next section header
        pTempHeader:=PImageSectionHeader(CalcOffset([pTempHeader, Pointer(SizeOf(IMAGE_SECTION_HEADER))]));
     end;
     // Return the section
     result:=PImageSectionHeader(CalcOffset([pSecHeader, Pointer(dwPos * SizeOf(IMAGE_SECTION_HEADER))]));
  end
  else
     // Not a valid image
     result:=nil;

end;

function FindLastPhysicalSection(pImageBase: Pointer): PImageSectionHeader;
var  pDosHeader:       PImageDosHeader;
     pNtHeaders:       PImageNtHeaders;
     pFileHeader:      PImageFileHeader;
     pOptHeader:       PImageOptionalHeader;
     pSecHeader:       PImageSectionHeader;
     pTempHeader:      PImageSectionHeader;
     pNtSignature:     PLongWord;
     dwCurrentMaxPA:   DWORD;
     dwPos:            Integer;
     dwIndex:          Integer;
begin

  // Get DOS header
  pDosHeader:=pImageBase;

  // Get PE header location
  pNtSignature:=PLongWord(CalcOffset([pImageBase, Pointer(pDosHeader._lfanew)]));

  // Check PE signature
  if (pNtSignature^ = IMAGE_NT_SIGNATURE) then
  begin
     // Save the NT header
     pNtHeaders:=PImageNtHeaders(pNtSignature);
     // Push past the signature
     Inc(PChar(pNtSignature), SizeOf(LongWord));
     // Find an offset to the main PE header
     pFileHeader:=PImageFileHeader(pNtSignature);
     // Get optional PE header
     pOptHeader:=PImageOptionalHeader(CalcOffset([pFileHeader, Pointer(IMAGE_SIZEOF_FILE_HEADER)]));
     // Get first section header
     pSecHeader:=PImageSectionHeader(CalcOffset([pOptHeader, Pointer(pFileHeader^.SizeOfOptionalHeader)]));
     // Save first section header
     dwPos:=0;
     dwCurrentMaxPA:=0;
     pTempHeader:=pSecHeader;
     // Walk the sections
     for dwIndex:=0 to Pred(pNtHeaders^.FileHeader.NumberOfSections) do
     begin
        // Check raw data pointer
        if (pTempHeader^.PointerToRawData > dwCurrentMaxPA) then
        begin
           // Update current max PA
           dwCurrentMaxPA:=pTempHeader^.PointerToRawData;
           // Save index
           dwPos:=dwIndex;
        end;
        // Get next section header
        pTempHeader:=PImageSectionHeader(CalcOffset([pTempHeader, Pointer(SizeOf(IMAGE_SECTION_HEADER))]));
     end;
     // Return the section
     result:=PImageSectionHeader(CalcOffset([pSecHeader, Pointer(dwPos * SizeOf(IMAGE_SECTION_HEADER))]));
  end
  else
     // Not a valid image
     result:=nil;

end;

function FindFirstSection(pImageBase: Pointer): PImageSectionHeader;
begin

  // Same as GetSectionHeader
  result:=GetSectionHeader(pImageBase);

end;

function FindNextSection(pImageBase: Pointer; CurrentSection: PImageSectionHeader): PImageSectionHeader;
var  pDosHeader:       PImageDosHeader;
     pNtHeaders:       PImageNtHeaders;
     pFileHeader:      PImageFileHeader;
     pOptHeader:       PImageOptionalHeader;
     pSecHeader:       PImageSectionHeader;
     pPrevHeader:      PImageSectionHeader;
     pCurrHeader:      PImageSectionHeader;
     pNtSignature:     PLongWord;
     dwIndex:          Integer;
begin

  // Set default result
  result:=nil;

  // Get DOS header
  pDosHeader:=pImageBase;

  // Get PE header location
  pNtSignature:=PLongWord(CalcOffset([pImageBase, Pointer(pDosHeader._lfanew)]));

  // Check PE signature
  if (pNtSignature^ = IMAGE_NT_SIGNATURE) then
  begin
     // Save the NT header
     pNtHeaders:=PImageNtHeaders(pNtSignature);
     // Push past the signature
     Inc(PChar(pNtSignature), SizeOf(LongWord));
     // Find an offset to the main PE header
     pFileHeader:=PImageFileHeader(pNtSignature);
     // Get optional PE header
     pOptHeader:=PImageOptionalHeader(CalcOffset([pFileHeader, Pointer(IMAGE_SIZEOF_FILE_HEADER)]));
     // Get first section header
     pSecHeader:=PImageSectionHeader(CalcOffset([pOptHeader, Pointer(pFileHeader^.SizeOfOptionalHeader)]));
     // Check section count
     if (pNtHeaders^.FileHeader.NumberOfSections > 1) then
     begin
        // Save prev and current headers
        pPrevHeader:=pSecHeader;
        pCurrHeader:=PImageSectionHeader(CalcOffset([pSecHeader, Pointer(SizeOf(IMAGE_SECTION_HEADER))]));
        // Walk sections starting with the second in the list
        for dwIndex:=1 to Pred(pNtHeaders^.FileHeader.NumberOfSections) do
        begin
           // Check to see if prev = passed section
           if (pPrevHeader = CurrentSection) then
           begin
              // Return next section
              result:=pCurrHeader;
              // Done processing
              break;
           end;
           // Chain next section
           pPrevHeader:=pCurrHeader;
           pCurrHeader:=PImageSectionHeader(CalcOffset([pCurrHeader, Pointer(SizeOf(IMAGE_SECTION_HEADER))]));
        end;
     end;
  end;

end;

function FindSection(pImageBase: Pointer; SectionBase: DWORD): PImageSectionHeader;
var  pDosHeader:       PImageDosHeader;
     pNtHeaders:       PImageNtHeaders;
     pFileHeader:      PImageFileHeader;
     pOptHeader:       PImageOptionalHeader;
     pSecHeader:       PImageSectionHeader;
     pNtSignature:     PLongWord;
     dwIndex:          Integer;
begin

  // Set default result
  result:=nil;

  // Get DOS header
  pDosHeader:=pImageBase;

  // Get PE header location
  pNtSignature:=PLongWord(CalcOffset([pImageBase, Pointer(pDosHeader._lfanew)]));

  // Check PE signature
  if (pNtSignature^ = IMAGE_NT_SIGNATURE) then
  begin
     // Save the NT header
     pNtHeaders:=PImageNtHeaders(pNtSignature);
     // Push past the signature
     Inc(PChar(pNtSignature), SizeOf(LongWord));
     // Find an offset to the main PE header
     pFileHeader:=PImageFileHeader(pNtSignature);
     // Get optional PE header
     pOptHeader:=PImageOptionalHeader(CalcOffset([pFileHeader, Pointer(IMAGE_SIZEOF_FILE_HEADER)]));
     // Get first section header
     pSecHeader:=PImageSectionHeader(CalcOffset([pOptHeader, Pointer(pFileHeader^.SizeOfOptionalHeader)]));
     // Walk the sections
     for dwIndex:=0 to Pred(pNtHeaders^.FileHeader.NumberOfSections) do
     begin
        // Check raw data pointer
        if (pSecHeader^.VirtualAddress = SectionBase) then
        begin
           // Return section
           result:=pSecHeader;
           // Done processing
           break;
        end;
        // Get next section header
        pSecHeader:=PImageSectionHeader(CalcOffset([pSecHeader, Pointer(SizeOf(IMAGE_SECTION_HEADER))]));
     end;
  end;

end;

procedure MakeAllSectionsWritable(pImageBase: Pointer);
var  pDosHeader:       PImageDosHeader;
     pNtHeaders:       PImageNtHeaders;
     pFileHeader:      PImageFileHeader;
     pOptHeader:       PImageOptionalHeader;
     pSecHeader:       PImageSectionHeader;
     pNtSignature:     PLongWord;
     dwIndex:          Integer;
begin

  // Get DOS header
  pDosHeader:=pImageBase;

  // Get PE header location
  pNtSignature:=PLongWord(CalcOffset([pImageBase, Pointer(pDosHeader._lfanew)]));

  // Check PE signature
  if (pNtSignature^ = IMAGE_NT_SIGNATURE) then
  begin
     // Save the NT header
     pNtHeaders:=PImageNtHeaders(pNtSignature);
     // Push past the signature
     Inc(PChar(pNtSignature), SizeOf(LongWord));
     // Find an offset to the main PE header
     pFileHeader:=PImageFileHeader(pNtSignature);
     // Get optional PE header
     pOptHeader:=PImageOptionalHeader(CalcOffset([pFileHeader, Pointer(IMAGE_SIZEOF_FILE_HEADER)]));
     // Get first section header
     pSecHeader:=PImageSectionHeader(CalcOffset([pOptHeader, Pointer(pFileHeader^.SizeOfOptionalHeader)]));
     // Walk the sections
     for dwIndex:=0 to Pred(pNtHeaders^.FileHeader.NumberOfSections) do
     begin
        // Update the characteristics
        pSecHeader^.Characteristics:=pSecHeader^.Characteristics or IMAGE_SCN_MEM_WRITE;
        // Get next section header
        pSecHeader:=PImageSectionHeader(CalcOffset([pSecHeader, Pointer(SizeOf(IMAGE_SECTION_HEADER))]));
     end;
  end;

end;

function AddSection(pImageBase: Pointer; CodeVirtualStart, CodeSize: DWORD): PImageSectionHeader;
var  pDosHeader:       PImageDosHeader;
     pNtHeaders:       PImageNtHeaders;
     pFileHeader:      PImageFileHeader;
     pOptHeader:       PImageOptionalHeader;
     pSecHeader:       PImageSectionHeader;
     pNtSignature:     PLongWord;
     dwSectionOffset:  DWORD;
begin

  // Get DOS header
  pDosHeader:=pImageBase;

  // Get PE header location
  pNtSignature:=PLongWord(CalcOffset([pImageBase, Pointer(pDosHeader._lfanew)]));

  // Check PE signature
  if (pNtSignature^ = IMAGE_NT_SIGNATURE) then
  begin
     // Save the NT header
     pNtHeaders:=PImageNtHeaders(pNtSignature);
     // Push past the signature
     Inc(PChar(pNtSignature), SizeOf(LongWord));
     // Find an offset to the main PE header
     pFileHeader:=PImageFileHeader(pNtSignature);
     // Get optional PE header
     pOptHeader:=PImageOptionalHeader(CalcOffset([pFileHeader, Pointer(IMAGE_SIZEOF_FILE_HEADER)]));
     // Get first section header
     pSecHeader:=PImageSectionHeader(CalcOffset([pOptHeader, Pointer(pFileHeader^.SizeOfOptionalHeader)]));
     // Calculate the new section offset
     dwSectionOffset:=DWORD(DWORD(pSecHeader) + pNtHeaders^.FileHeader.NumberOfSections * SizeOf(IMAGE_SECTION_HEADER) - DWORD(pImageBase));
     // Check whether there's room for a new section
     if (pNtHeaders^.OptionalHeader.SizeOfHeaders < (dwSectionOffset + SizeOf(IMAGE_SECTION_HEADER))) then
        // Failure
        result:=nil
     else
     begin
        // Get pointer to new section
        result:=PImageSectionHeader(CalcOffset([pImageBase, Pointer(dwSectionOffset)]));
        // Copy section data from previous section
        CopyMemory(result, PImageSectionHeader(PChar(result)-SizeOf(IMAGE_SECTION_HEADER)), SizeOf(IMAGE_SECTION_HEADER));
        // Update the PE header
        Inc(pNtHeaders^.FileHeader.NumberOfSections);
     end;
  end
  else
     // Not a valid image
     result:=nil;

end;

function EncryptSection(CodeSection: PImageSectionHeader; pImageBase: Pointer; Seed: DWORD): DWORD;
var  pData:            PByte;
     dwOldProtect:     DWORD;
     dwRawCP:          DWORD;
     dwVCS:            DWORD;
     dwStartPos:       DWORD;
     dwEndPos:         DWORD;
     dwSeed:           DWORD;
begin

  // Get raw data pointer and size
  dwRawCP:=CodeSection^.PointerToRawData;
  dwVCS:=CodeSection^.SizeOfRawData;

  // Get start position relative from image base
  dwStartPos:=DWORD(pImageBase) + dwRawCP;

  // Check code section name, push start position if rsrc
  if (StrIComp(PChar(@CodeSection^.Name), '.rsrc') = 0) then Inc(dwStartPos, $11);

  // Get end position for raw data
  dwEndPos:=dwStartPos + dwVCS;

  // Set starting seed value
  dwSeed:=Seed;

  // Unprotect code
  if VirtualProtect(pImageBase, dwEndPos - DWORD(pImageBase), PAGE_READWRITE, @dwOldProtect) then
  begin
     // Resource protection
     try
        // Encrypt the section data
        while (dwStartPos < dwEndPos) do
        begin
           // Get pointer to data
           pData:=PByte(Pointer(dwStartPos));
           // Add low byte of seed to data byte
           Inc(pData^, LoByte(LoWord(dwSeed)));
           // Missing piece
           //
           //    dwSeed:=GenerateRandomNumber(dwSeed);
           //
           // Push starting position
           Inc(dwStartPos);
        end;
     finally
        // Reset protection
        VirtualProtect(pImageBase, dwEndPos - DWORD(pImageBase), dwOldProtect, nil);
     end;
  end;

  // Return new seed
  result:=dwSeed;
 
end;

end.


0
 
Russell LibbySoftware Engineer, Advisory Commented:

Cosmin,
If no one picks this q up, I'll give you the conversion in the morning.

Regards,
Russell
0
 
2266180Commented:
I'll give you te conversion in the mornig as well ... 2 seconds before russel :D
kiddin :) (I'm too busy atm)
0
The 14th Annual Expert Award Winners

The results are in! Meet the top members of our 2017 Expert Awards. Congratulations to all who qualified!

 
anorganixAuthor Commented:
Thanks a lot guys... I really need it for finishing a exe-protector I'm working on...
I want to protect my apps, and I already have the ASM core (detour functions, etc) and the anti-debugging tricks, and this was tha last piece missing from the puzzle.

:: Cosmin
0
 
Russell LibbySoftware Engineer, Advisory Commented:
Cosmin,

I am done except for the last little bit of asm code; the code is trivial, BUT.... I can't complete it due to the missing call to:

-> GenerateRandomNumber

Do you have a reference (source) to this?

Russell
0
 
anorganixAuthor Commented:
Hi, and thanks a lot for your perfect translation...
I've managed to translate the GenerateRandomNumber, but not sure if it's ok, so here it is:

////////////////////// code /////////////////////////

__declspec( naked )void GenerateRandomNumber()
{
      // x_(r+1) = a*x_r + c modulo m
      _asm
      {
            push EBX;
            push ECX;
            push EDX;
            mov EBX, 1277;
            mul EBX; // EAX*1277 answer in EDX
            add EAX, 0; // +c

            sub EDX,EDX;
            mov EBX, 131072;
            div EBX; // m
            mov EAX, EDX;
            
            // we only want a byte of it

      //      mov BL, AL;
      //      sub EAX, EAX;
      //      mov AL, BL;

            pop EDX;
            pop ECX;
            pop EBX;
            ret;
      }

      /*  x := y mod z; {unsigned remainder}
            mov( y, eax );
            mov( 0, edx );       // Zero extend EAX into EDX.
            mod( z, edx:eax );
             mov( edx, x );       // Note that remainder is in EDX.      */
}

void GenerateRandomNumberEnd(){}

////////////////////// end code //////////////////

Anyway, the points are all yours!
Excellent job, as always...
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.