Author Topic: Question about Windows programming and section attributes  (Read 9046 times)

Offline ben321

  • Full Member
  • **
  • Posts: 185
Question about Windows programming and section attributes
« on: February 27, 2023, 01:10:19 PM »
I know you can override a section to have data or code like this
Code: [Select]
SECTION MySection1 data
SECTION MySection2 code

However, is it possible to label a section as containing both code and data, using NASM? I know the PE format supports this, because the section header has a flags field called Characteristics. This controls how the operating system interprets the contents of this section, whether it can be read, written, or executed (or any combination of these), as well as if it contains code, initialized data, or uninitialized data (or any combination of these). A section does NOT have to contain exclusively data or code. It can certainly contain both. Is it possible to achieve this with NASM? If so how? If not, consider this a feature request.

Offline fredericopissarra

  • Full Member
  • **
  • Posts: 373
  • Country: br
Re: Question about Windows programming and section attributes
« Reply #1 on: February 27, 2023, 01:29:55 PM »
See nasmdoc chapter 8.

Offline ben321

  • Full Member
  • **
  • Posts: 185
Re: Question about Windows programming and section attributes
« Reply #2 on: February 27, 2023, 02:27:12 PM »
See nasmdoc chapter 8.

Where do I download NASM Doc?

Update:
Nevermind, I found it here https://www.nasm.us/xdoc/2.16.01/html/nasmdoc0.html



Update2:
I was reading chapter 8 here https://www.nasm.us/xdoc/2.16.01/html/nasmdoc8.html like you said, and unless I somehow overlooked it, it seems none of the Windows output object formats like COFF or WIN32 (depending on which linker you plan to use) indicate that you can combine multiple section characteristics such as data+code. If I'm wrong here, please let me know.
« Last Edit: February 27, 2023, 02:35:27 PM by ben321 »

Offline fredericopissarra

  • Full Member
  • **
  • Posts: 373
  • Country: br
Re: Question about Windows programming and section attributes
« Reply #3 on: February 27, 2023, 05:02:20 PM »
Depending on the mode of operation (i386 or x86-64) this can be impossible.

i386 mode uses different segment selectors for code and data and code segments can be only executed and/or read (not write!). Unless the data descriptor is mapped to the sabe linear address space that of the codeseg, you can't write in codeseg.

In x86-64 there's no segmentation, but the page write code is in can be marked as read-only.

See Intel SDM volume 3 about protection and memory management.

This code is valid on i386/x86-64 modes (because only READs the msg bytes, don't write on this region):
Code: [Select]
  ; i386 mode Win32 hello using only a text segment.
  ;
  ; nasm -fwin32 -o test.o test.asm
  ; ld -s -o test.exe test.o -lkernel32
  ;
  bits  32

  section .text

  extern __imp__GetStdHandle@4
  extern __imp__WriteConsoleA@20
  extern __imp__ExitProcess@4

  global _start
_start:
  ; Get STDOUT handle.
  push  -11
  call  [__imp__GetStdHandle@4]

  push  0
  push  0
  push  msg_len
  push  msg
  push  eax
  call  [__imp__WriteConsoleA@20]

  push  0
  jmp   [__imp__ExitProcess@4]

  ; Notice: this is in .text section!
  ; Can read, but can't write!
msg:
  db    `Hello\r\n`
msg_len equ $ - msg

Try to add mov byte [msg + 5],0 before calling WriteConsoleA and you'll get an 'segmentation fault'.
« Last Edit: February 27, 2023, 05:07:18 PM by fredericopissarra »

Offline ben321

  • Full Member
  • **
  • Posts: 185
Re: Question about Windows programming and section attributes
« Reply #4 on: February 27, 2023, 08:01:45 PM »
Depending on the mode of operation (i386 or x86-64) this can be impossible.

i386 mode uses different segment selectors for code and data and code segments can be only executed and/or read (not write!). Unless the data descriptor is mapped to the sabe linear address space that of the codeseg, you can't write in codeseg.

In x86-64 there's no segmentation, but the page write code is in can be marked as read-only.

See Intel SDM volume 3 about protection and memory management.

This code is valid on i386/x86-64 modes (because only READs the msg bytes, don't write on this region):
Code: [Select]
  ; i386 mode Win32 hello using only a text segment.
  ;
  ; nasm -fwin32 -o test.o test.asm
  ; ld -s -o test.exe test.o -lkernel32
  ;
  bits  32

  section .text

  extern __imp__GetStdHandle@4
  extern __imp__WriteConsoleA@20
  extern __imp__ExitProcess@4

  global _start
_start:
  ; Get STDOUT handle.
  push  -11
  call  [__imp__GetStdHandle@4]

  push  0
  push  0
  push  msg_len
  push  msg
  push  eax
  call  [__imp__WriteConsoleA@20]

  push  0
  jmp   [__imp__ExitProcess@4]

  ; Notice: this is in .text section!
  ; Can read, but can't write!
msg:
  db    `Hello\r\n`
msg_len equ $ - msg

Try to add mov byte [msg + 5],0 before calling WriteConsoleA and you'll get an 'segmentation fault'.

I'm using 64bit Windows but am writing a 32bit program. When I look at the EXE output from NASM in a hex editor, the Characteristics field in the section header for the .text section, I see the bytes 0x20, 0x00, 0x00, 0x60. The first byte is the one that tells the OS what type of content is in it. 0x20 is code. 0x40 would be data. 0x60 would be both code and data. The last byte says 0x60, and this is the protection byte. The value 0x60 here means that reading and executing are permitted. 0x20 would mean executing code is permitted, 0x40 would mean reading is permitted, and 0x80 would mean writing is permitted. The actual permissions granted is a combination of one or more of these flags. In the case of the .text section output by NASM and GoLink, the value here is 0x60, meaning read and execute permissions are granted, but writing permission is not granted. In OllyDbg, such a section has its permissions shown as "R E". If it also had writing permission, it would show as "RWE". The resulting flag value for such an RWE section would be 0xE0 (the sum of 0x20 + 0x40 + 0x80). And yes, I've tested it by using a hex editor and manually setting the write permission in this way. And it works fine.

I just don't want to have to hexedit my EXE after every single compilation, in order to get my code to work. It would be nice, if NASM provided a way to set these permission flags for each section. Those permission flags would then get stored in the MS style COFF file that's output from the WIN32 format from NASM, and then the linker would be forced to give those permissions to that section when it generated the EXE file. I'm surprised that NASM doesn't have this feature yet. Anybody wanting to make self modifying code will NEED this feature.

Things like EXE compressors (as well as EXE obfuscators to try to stop reverse engineering) do this all the time. When such a tool is run on an EXE, it compresses the code section and puts it in a new section, and replaces the original code section with decompression or decryption code, as well as creating a third section that is uninitialized (the section header says where it should be allocated, but the EXE file itself contains no data or code to fill it). When you run the EXE, it runs the decryption or decompression code, and puts the output of this operation into the third section, and then jumps to that new section. Guess what type of permissions that third section has. Yep, it has both write and execute permissions. So that way the decompressed/decrypted code can be written into the third section and executed.


I'm just wondering if NASM has a feature to assign such access permissions to sections, even if it's not a documented feature. If not a feature now, it should certainly be added as soon as the devs have the time to do so.
« Last Edit: February 27, 2023, 08:08:21 PM by ben321 »