Method to determine if an exe file has been compressed with UPX

ε祈祈猫儿з 提交于 2019-12-01 05:04:17

Another Method, when a exe is packed with the UPX tool, the section of the PE header contains sections called UPX0,UPX1, etc. so if read these sections and compare the name with the string UPX you can determine if the exe was compressed using the UPX packer.

check this function

uses 
Windows;

function IsUPXCompressed(const Filename:TFileName): Boolean;
var
  i             : integer;
  pBaseAddress  : PByte;
  pDosHeader    : PImageDosHeader;
  pNtHeaders    : PImageNtHeaders;
  hFile         : Cardinal;
  hFileMap      : Cardinal;
  pSectionHeader: PImageSectionHeader;
  dwOffset      : Cardinal;
  SectName      : AnsiString;
begin
  Result:=False;

  hFile := CreateFile(PChar(Filename), GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
  if (hFile = INVALID_HANDLE_VALUE) then Exit;

  hFileMap := CreateFileMapping(hFile, nil, PAGE_READONLY or SEC_IMAGE,  0, 0, nil);
  if (hFileMap = 0) then
  begin
    CloseHandle(hFile);
    Exit;
  end;

  pBaseAddress := MapViewOfFile(hFileMap, FILE_MAP_READ, 0, 0, 0);
  if (pBaseAddress = nil) then
  begin
    CloseHandle(hFileMap);
    CloseHandle(hFile);
    Exit;
  end;

  try
      dwOffset   := Cardinal(pBaseAddress);
      pDosHeader := PImageDosHeader(pBaseAddress);
      pNtHeaders := PImageNtHeaders(dwOffset + Cardinal(pDosHeader._lfanew));
      pSectionHeader := pImageSectionHeader(Cardinal(pNtHeaders) + SizeOf(TImageNtHeaders));
      for i := 0 to pNtHeaders.FileHeader.NumberOfSections-1 do
      begin
        SetString(SectName, PAnsiChar(@pSectionHeader.Name), SizeOf(pSectionHeader.Name));
        Result:=Pos('UPX',SectName)>0;
        If Result then break;
        Inc(pSectionHeader);
      end;

  finally
    UnmapViewOfFile(pBaseAddress);
    CloseHandle(hFileMap);
    CloseHandle(hFile);
  end;

end;

try to uncompress it with upx?

UPX itself does it like this:

if (memcmp(isection[0].name,"UPX",3) == 0)
    throwAlreadyPackedByUPX();

This is the implementation for 32-bit PEs; 64-bit PEs need different offsets, and other executable formats have to be handled separately.

#include <stdio.h>

typedef unsigned int uint;

uint peek_d( FILE* f, uint offs ) {
  fseek( f, offs, SEEK_SET );
  uint a = 0;
  fread( &a, 1,sizeof(a), f );
  return a;
}

int main( int argc, char** argv ) {

  FILE* f = fopen( argv[1], "rb" ); if( f==0 ) return 1;

  uint p,n,x,y;

  p = peek_d( f, 0x3C ); // PE header offset
  n = peek_d( f, p+0x74 ); // pointer table size
  x = p + 0x78 + n*8;
  y = peek_d( f, x+0*0x28+0 ); // 1st section name

  if( (y&0xFFFFFF) == ('U'+('P'<<8)+('X'<<16)) ) {
    printf( "UPX detected!\n" );
  } else {
    printf( "No UPX!\n" );
  }

  return 0;
}

// Returns IsUPXCompressed - Modified for Delphi 2010

function IsUPXCompressed( const Filename: TFileName ): Boolean;
var
  i: integer;
  pBaseAddress: PByte;
  pDosHeader: PImageDosHeader;
  pNtHeaders: PImageNtHeaders;
  hFile: Cardinal;
  hFileMap: Cardinal;
  pSectionHeader: PImageSectionHeader;
  dwOffset: Cardinal;
  SectName: AnsiString;
begin
  Result := False;
  hFile := CreateFile( PChar( Filename ), GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0 );
  if ( hFile = INVALID_HANDLE_VALUE ) then
    Exit;
  hFileMap := CreateFileMapping( hFile, nil, PAGE_READONLY or SEC_IMAGE, 0, 0, nil );
  if ( hFileMap = 0 ) then
  begin
    CloseHandle( hFile );
    Exit;
  end;
  pBaseAddress := MapViewOfFile( hFileMap, FILE_MAP_READ, 0, 0, 0 );
  if ( pBaseAddress = nil ) then
  begin
    CloseHandle( hFileMap );
    CloseHandle( hFile );
    Exit;
  end;
  dwOffset := Cardinal( pBaseAddress );
  pDosHeader := PImageDosHeader( pBaseAddress );
  pNtHeaders := PImageNtHeaders( dwOffset + Cardinal( pDosHeader._lfanew ) );
  pSectionHeader := pImageSectionHeader( Cardinal( pNtHeaders ) + SizeOf( TImageNtHeaders ) );
  for i := 0 to pNtHeaders.FileHeader.NumberOfSections - 1 do
  begin
    SetString( SectName, PAnsiChar( @pSectionHeader.name ), SizeOf( pSectionHeader.name ) );
    if Pos( 'UPX', SectName ) > 0 then
    begin
      Result := True;
      exit;
    end;
    Inc( pSectionHeader );
  end;
end;

Thanks Rob for the pointers.

The section names are not included the UPX word always. It mabebe contain another name changed by user. For certain. Ypu must search for UPX copmpressor signature in the whole file.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!