Is there a method to determine if an exe file has been compressed with UPX?
The function to determine if an exe file has been compressed is excellent except I found a problem with the code. If the function IsUPXCompressed is called then you try to run upx, upx can not save the file it modifies. There is something not sharing rights correctly in the function. I have tested this for several hours. If I do not call the method then UPX can write the files with no problem. You you call it then try to run UPX it will not save the file. UPX reports an IOException Permission denied error when trying to write the file.
Can anyone spot something wrong in the code that would cause this problem?
Thank-you
The function to determine if an exe file has been compressed is excellent except I found a problem with the code. If the function IsUPXCompressed is called then you try to run upx, upx can not save the file it modifies. There is something not sharing rights correctly in the function. I have tested this for several hours. If I do not call the method then UPX can write the files with no problem. You you call it then try to run UPX it will not save the file. UPX reports an IOException Permission denied error when trying to write the file.
Can anyone spot something wrong in the code that would cause this problem?
Thank-you
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;
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;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With