[Okta Webinar] Learn how to a build a cloud-first strategyRegister Now

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1397
  • Last Modified:

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.
0
anorganix
Asked:
anorganix
  • 3
  • 2
1 Solution
 
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
 
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
Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

 
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
 
Russell LibbySoftware 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
 
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

Featured Post

Free Tool: Port Scanner

Check which ports are open to the outside world. Helps make sure that your firewall rules are working as intended.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

  • 3
  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now