program segments(section) Topic is solved

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
whynotregister
Posts: 147
Joined: 05 Nov 2016, 22:42

program segments(section)

15 Nov 2017, 23:52

Image

I want to get the segment name of the program like the picture above. What should I do? :D
User avatar
Gio
Posts: 1247
Joined: 30 Sep 2013, 10:54
Location: Brazil

Re: program segments(section)  Topic is solved

16 Nov 2017, 23:19

Hello Whynotregister.

That informartion is actually stored as ASCII encoded text inside the executable file. It can be isolated by following (calculating) the many offsets (including the offsets of offsets and so on) of information inside the PE file untill you reach the section table. The names of the sections can than be collected from there.

Below is an example on how to achieve this.

Code: Select all

FileSelectFile, SELECTED_FILE,,,Select the PE file you wish to obtain the sections header names from, Executable Files (*.exe)

BinRead(SELECTED_FILE, FILE_RAW_CONTENTS, 10000) ; BinRead 10Kb. No need to read even nearly as much, but just in case...

NUMBER_OF_DOS_HEADER_16_BYTE_BLOCKS := "0x" . SubStr(FILE_RAW_CONTENTS, 19, 2) . SubStr(FILE_RAW_CONTENTS, 17, 2)

DOS_HEADER_SIZE := 0x10 * NUMBER_OF_DOS_HEADER_16_BYTE_BLOCKS

PE_HEADER_OFFSET := "0x" . SubStr(FILE_RAW_CONTENTS, (DOS_HEADER_SIZE * 2) - 1, 2) . SubStr(FILE_RAW_CONTENTS, (DOS_HEADER_SIZE * 2) - 3, 2) . SubStr(FILE_RAW_CONTENTS, (DOS_HEADER_SIZE * 2) - 5, 2) . SubStr(FILE_RAW_CONTENTS, (DOS_HEADER_SIZE * 2) - 7, 2)

;This is the first info we need.
NUMBER_OF_SECTIONS := "0x" . SubStr(FILE_RAW_CONTENTS, (PE_HEADER_OFFSET * 2) + 15, 2) . SubStr(FILE_RAW_CONTENTS, (PE_HEADER_OFFSET * 2) + 13, 2)

SIZE_OF_IMAGE_OPTIONAL_HEADER := "0x" . SubStr(FILE_RAW_CONTENTS, (PE_HEADER_OFFSET * 2) + 43,2) . SubStr(FILE_RAW_CONTENTS, (PE_HEADER_OFFSET * 2) + 41,2)

; Loop below collects the second information we need (names of sections).
SECTION_NAMES := Object()
Loop % NUMBER_OF_SECTIONS
{
	CURRENT_SECTION := A_Index
	CURRENT_SECTION_NAME := ""
	Loop 8
	{
		CURRENT_SECTION_NAME .= Chr( "0x" . SubStr(FILE_RAW_CONTENTS, (PE_HEADER_OFFSET * 2) + 49 + (SIZE_OF_IMAGE_OPTIONAL_HEADER * 2) + ((A_Index - 1) * 2) + ((CURRENT_SECTION - 1) * 80), 2) )
	}
	SECTION_NAMES[A_Index] := CURRENT_SECTION_NAME
}

Loop % NUMBER_OF_SECTIONS
{
	MSGBOX % SECTION_NAMES[A_Index]
}


Return
;################################################;
; BinRead() By Laszlo (https://autohotkey.com/board/topic/4299-simple-binary-file-readwrite-functions/)
;################################################;

/* ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; BinRead ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|  - Open binary file
|  - Read n bytes (n = 0: all)
|  - From offset (offset < 0: counted from end)
|  - Close file
|  data (replaced) <- file[offset + 0..n-1]
|  Return #bytes actually read
*/ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

BinRead(file, ByRef data, n=0, offset=0)
{
   h := DllCall("CreateFile","Str",file,"Uint",0x80000000,"Uint",3,"UInt",0,"UInt",3,"Uint",0,"UInt",0)
   IfEqual h,-1, SetEnv, ErrorLevel, -1
   IfNotEqual ErrorLevel,0,Return,0 ; couldn't open the file

   m = 0                            ; seek to offset
   IfLess offset,0, SetEnv,m,2
   r := DllCall("SetFilePointerEx","Uint",h,"Int64",offset,"UInt *",p,"Int",m)
   IfEqual r,0, SetEnv, ErrorLevel, -3
   IfNotEqual ErrorLevel,0, {
      t = %ErrorLevel%              ; save ErrorLevel to be returned
      DllCall("CloseHandle", "Uint", h)
      ErrorLevel = %t%              ; return seek error
      Return 0
   }

   TotalRead = 0
   data =
   IfEqual n,0, SetEnv n,0xffffffff ; almost infinite

   format = %A_FormatInteger%       ; save original integer format
   SetFormat Integer, Hex           ; for converting bytes to hex

   Loop %n%
   {
      result := DllCall("ReadFile","UInt",h,"UChar *",c,"UInt",1,"UInt *",Read,"UInt",0)
      if (!result or Read < 1 or ErrorLevel)
         break
      TotalRead += Read             ; count read
      c += 0                        ; convert to hex
      StringTrimLeft c, c, 2        ; remove 0x
      c = 0%c%                      ; pad left with 0
      StringRight c, c, 2           ; always 2 digits
      data = %data%%c%              ; append 2 hex digits
   }

   IfNotEqual ErrorLevel,0, SetEnv,t,%ErrorLevel%

   h := DllCall("CloseHandle", "Uint", h)
   IfEqual h,-1, SetEnv, ErrorLevel, -2
   IfNotEqual t,,SetEnv, ErrorLevel, %t%

   SetFormat Integer, %format%      ; restore original format
   Totalread += 0                   ; convert to original format
   Return TotalRead
}
Return
One thing to keep in mind is that if the executable in question is compressed or packed, the section names retrieved will belong to the packers code, not to the unpacked PE.

Feel free to ask any questions about the code above or the PE file format and structure if you would like to.

Best wishes.
whynotregister
Posts: 147
Joined: 05 Nov 2016, 22:42

Re: program segments(section)

17 Nov 2017, 00:25

Gio wrote:Hello Whynotregister.

That informartion is actually stored as ASCII encoded text inside the executable file. It can be isolated by following (calculating) the many offsets (including the offsets of offsets and so on) of information inside the PE file untill you reach the section table. The names of the sections can than be collected from there.

Below is an example on how to achieve this.

Code: Select all

FileSelectFile, SELECTED_FILE,,,Select the PE file you wish to obtain the sections header names from, Executable Files (*.exe)

BinRead(SELECTED_FILE, FILE_RAW_CONTENTS, 10000) ; BinRead 10Kb. No need to read even nearly as much, but just in case...

NUMBER_OF_DOS_HEADER_16_BYTE_BLOCKS := "0x" . SubStr(FILE_RAW_CONTENTS, 19, 2) . SubStr(FILE_RAW_CONTENTS, 17, 2)

DOS_HEADER_SIZE := 0x10 * NUMBER_OF_DOS_HEADER_16_BYTE_BLOCKS

PE_HEADER_OFFSET := "0x" . SubStr(FILE_RAW_CONTENTS, (DOS_HEADER_SIZE * 2) - 1, 2) . SubStr(FILE_RAW_CONTENTS, (DOS_HEADER_SIZE * 2) - 3, 2) . SubStr(FILE_RAW_CONTENTS, (DOS_HEADER_SIZE * 2) - 5, 2) . SubStr(FILE_RAW_CONTENTS, (DOS_HEADER_SIZE * 2) - 7, 2)

;This is the first info we need.
NUMBER_OF_SECTIONS := "0x" . SubStr(FILE_RAW_CONTENTS, (PE_HEADER_OFFSET * 2) + 15, 2) . SubStr(FILE_RAW_CONTENTS, (PE_HEADER_OFFSET * 2) + 13, 2)

SIZE_OF_IMAGE_OPTIONAL_HEADER := "0x" . SubStr(FILE_RAW_CONTENTS, (PE_HEADER_OFFSET * 2) + 43,2) . SubStr(FILE_RAW_CONTENTS, (PE_HEADER_OFFSET * 2) + 41,2)

; Loop below collects the second information we need (names of sections).
SECTION_NAMES := Object()
Loop % NUMBER_OF_SECTIONS
{
	CURRENT_SECTION := A_Index
	CURRENT_SECTION_NAME := ""
	Loop 8
	{
		CURRENT_SECTION_NAME .= Chr( "0x" . SubStr(FILE_RAW_CONTENTS, (PE_HEADER_OFFSET * 2) + 49 + (SIZE_OF_IMAGE_OPTIONAL_HEADER * 2) + ((A_Index - 1) * 2) + ((CURRENT_SECTION - 1) * 80), 2) )
	}
	SECTION_NAMES[A_Index] := CURRENT_SECTION_NAME
}

Loop % NUMBER_OF_SECTIONS
{
	MSGBOX % SECTION_NAMES[A_Index]
}


Return
;################################################;
; BinRead() By Laszlo (https://autohotkey.com/board/topic/4299-simple-binary-file-readwrite-functions/)
;################################################;

/* ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; BinRead ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|  - Open binary file
|  - Read n bytes (n = 0: all)
|  - From offset (offset < 0: counted from end)
|  - Close file
|  data (replaced) <- file[offset + 0..n-1]
|  Return #bytes actually read
*/ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

BinRead(file, ByRef data, n=0, offset=0)
{
   h := DllCall("CreateFile","Str",file,"Uint",0x80000000,"Uint",3,"UInt",0,"UInt",3,"Uint",0,"UInt",0)
   IfEqual h,-1, SetEnv, ErrorLevel, -1
   IfNotEqual ErrorLevel,0,Return,0 ; couldn't open the file

   m = 0                            ; seek to offset
   IfLess offset,0, SetEnv,m,2
   r := DllCall("SetFilePointerEx","Uint",h,"Int64",offset,"UInt *",p,"Int",m)
   IfEqual r,0, SetEnv, ErrorLevel, -3
   IfNotEqual ErrorLevel,0, {
      t = %ErrorLevel%              ; save ErrorLevel to be returned
      DllCall("CloseHandle", "Uint", h)
      ErrorLevel = %t%              ; return seek error
      Return 0
   }

   TotalRead = 0
   data =
   IfEqual n,0, SetEnv n,0xffffffff ; almost infinite

   format = %A_FormatInteger%       ; save original integer format
   SetFormat Integer, Hex           ; for converting bytes to hex

   Loop %n%
   {
      result := DllCall("ReadFile","UInt",h,"UChar *",c,"UInt",1,"UInt *",Read,"UInt",0)
      if (!result or Read < 1 or ErrorLevel)
         break
      TotalRead += Read             ; count read
      c += 0                        ; convert to hex
      StringTrimLeft c, c, 2        ; remove 0x
      c = 0%c%                      ; pad left with 0
      StringRight c, c, 2           ; always 2 digits
      data = %data%%c%              ; append 2 hex digits
   }

   IfNotEqual ErrorLevel,0, SetEnv,t,%ErrorLevel%

   h := DllCall("CloseHandle", "Uint", h)
   IfEqual h,-1, SetEnv, ErrorLevel, -2
   IfNotEqual t,,SetEnv, ErrorLevel, %t%

   SetFormat Integer, %format%      ; restore original format
   Totalread += 0                   ; convert to original format
   Return TotalRead
}
Return
One thing to keep in mind is that if the executable in question is compressed or packed, the section names retrieved will belong to the packers code, not to the unpacked PE.

Feel free to ask any questions about the code above or the PE file format and structure if you would like to.

Best wishes.

Thank you very much. It has helped a lot. :D

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: Aqualest, Google [Bot] and 329 guests