Показаны сообщения с ярлыком 64bit. Показать все сообщения
Показаны сообщения с ярлыком 64bit. Показать все сообщения

понедельник, 23 августа 2021 г.

functions pointers in linux kernel data sections

I wrote simple program to estimate size of problem. Yes, I know about CFI but it seems that even on kernel 5.11 on fresh Ubuntu this mechanism is not implemented and indirect calls looks like:

  mov     rax, cs:XXX
  call    __x86_indirect_thunk_rax

__x86_indirect_thunk_rax proc near: 
  jmp     rax

First approach is just to scan .data section - you can do this running

./lkmem path-to-unpacked-kernel path-to-System.map

Some results:
  • arm64 5.11.0: 9893
  • x64 5.8-53: 10698
  • x64 5.11.0: 13414
  • x64 4.18: 16224
Ok, how about not yet inited pointers (or pointers in .bss section)? We need use disassembler - just disasm all functions in .text and find indirect calls and calls to __x86_indirect_thunk_XXX. Results (with -d option):
  • x64 4.18: +42
  • x64 5.8-53: +52
  • x64 5.11.0: +45
and with .bss section (option -b):
  • x64 4.18: +99
  • x64 5.8-53: +120
  • x64 5.11.0: +109

понедельник, 25 января 2021 г.

W32pServiceTable from windows 10 build 20292 64bit

 It seems that MS cut off whole apfnSimpleCall dispatching - no more functions

  • NtUserCallHwndParamLock
  • NtUserCallHwndParam
  • NtUserCallHwndLockSafe
  • NtUserCallHwndParamLockSafe
  • NtUserCallHwndLock
  • NtUserCallHwnd
  • NtUserCallNoParam
  • NtUserCallTwoParam
  • NtUserCallOneParam
  • NtUserCallHwndSafe
  • NtUserCallHwndOpt
Instead all functions from apfnSimpleCall now exported and contained in W32pServiceTable. Like (just to name few):
  • CreateMenu -> NtUserCreateMenu
  • CreatePopupMenu -> NtUserCreatePopupMenu
  • AllowForegroundActivation -> NtUserAllowForegroundActivation
etc etc
content of W32pServiceTable (W32pServiceLimit .eq. 0x5AA):

четверг, 21 мая 2020 г.

kernel pte in windows 10 64bit

Quarantine is a good time to re-read some old but useful papers and check if you can catch trick with making KUSER_SHARED_DATA writable again So lets see what we need:
  • some logic to extract PTE base from MiGetPteAddress
  • primitive to check if some address is valid - I used MmIsAddressValid
  • primitive to read page from kernel memory
Start with some system info:
pSystemRangeStart: FFFF800000000000
PTE base address: FFFF880000000000
PTE mask: 7FFFFFFFF8
PTE shift: 9

Do some calculation
function to get offset to PTE looks like:
return (address >> 9) & 0x7FFFFFFFF8;

for pSystemRangeStart PTE will be
4000000000 + pte_base = FFFF884000000000
You may notice that this address located above pte_base

for last available address in system FFFFFFFFFFFFFFFF PTE will be
7FFFFFFFF8 + pte_base = FFFF887FFFFFFFF8

Also we need some inverse function to convert from PTE to page address. First we need sub pte_base, then divide on sizeof(MMPTE_HARDWARE) and then multiply to size of page. And add some base address. Try to calculate this base for example for PTE of pSystemRangeStart FFFF884000000000:
(FFFF884000000000 - FFFF880000000000) / sizeof(MMPTE_HARDWARE) * 0x1000 = 800000000000

Our base is FFFF800000000000 (value of pSystemRangeStart) - 800000000000 = FFFF000000000000

Notice that this base does not match with pSystemRangeStart
So our inverse function may looks like:
return 0xFFFF000000000000 + (ptr_addr - pte_base) / sizeof(MMPTE_HARDWARE) * 0x1000;

Ok, it seems that we have all puzzle pieces and can scan all PTE from FFFF884000000000 to FFFF887FFFFFFFF8. Yes, all 0x4000000000 bytes - 256Gb. Sure, we can wait for results before retirement

четверг, 16 апреля 2020 г.

KiTpExcludedRoutines

As you can guess from name this is array of functions for which you can`t set kernel tracepoint. Curious that this lists differs in x64 and arm64
x64

четверг, 2 марта 2017 г.

ida plugin for RFG fixups processing

I commited today code for Ida Pro plugin for RFG fixups processing - for both version 1 & 2

It seems that by default during automatic loading of pe files Ida don`t load .reloc section (where usually located RFG fixups). In such case I ask if you want to add new segment:
Sure it works only if original input file (you can extract it with get_input_file_path function) is still available. Also I used dirty hack - I am too lazy to parse PE file by hand, and it seems that node "$ PE header" keeps all sections (even not loaded in base !) in supvals

enjoy

Update: it seems that buggy ida sdk don`t contains doCode function and auto_mark_range actually does not take into account end argument, so body of prologs looks ugly

вторник, 15 ноября 2016 г.

W32pServiceTableFilter from windows 10 build 14951 x64

kd> ? nt!KeServiceDescriptorTableFilter
Evaluate expression: -8795428636992 = fffff800`2799b6c0

kd> dps fffff800`2799b6c0
fffff800`2799b6c0  fffff800`278f4450 nt!KiServiceTable
fffff800`2799b6c8  00000000`00000000
fffff800`2799b6d0  00000000`000001c4
fffff800`2799b6d8  fffff800`278f4b64 nt!KiArgumentTable
fffff800`2799b6e0  ffffa344`ba544bc0 win32k!W32pServiceTableFilter

fffff800`2799b6e8  00000000`00000000
fffff800`2799b6f0  00000000`0000049c
fffff800`2799b6f8  ffffa344`ba5462d4 win32k!W32pArgumentTableFilter

среда, 19 октября 2016 г.

rfg patches in windows 10 build 14942

Lets see for example body of function user32!GetCursor:
.text:00000001800026E0             GetCursor       proc near          .text:00000001800026E0 66 90                   xchg    ax, ax
.text:00000001800026E2 0F 1F 80 00 00 00 00    nop     dword ptr [rax+00000000h]
.text:00000001800026E9 B9 06 00 00 00          mov     ecx, 6
.text:00000001800026EE 48 FF 25 EB 76 09 00    jmp cs:__imp_NtUserGetThreadState
.text:00000001800026EE                         GetCursor       endp
.text:00000001800026F5 90 90 90 90 90 90 90 90                 db 8 dup(90h)


and in debugger:
0:007> ? user32!GetCursor
Evaluate expression: 140732937348832 = 00007ffe`f0bd26e0
0:007> u 00007ffe`f0bd26e0
USER32!GetCursor:
00007ffe`f0bd26e0 488b0424        mov     rax,qword ptr [rsp]
00007ffe`f0bd26e4 6448890424      mov     qword ptr fs:[rsp],rax
00007ffe`f0bd26e9 b906000000      mov     ecx,6
00007ffe`f0bd26ee 644c8b1c24      mov     r11,qword ptr fs:[rsp]
00007ffe`f0bd26f3 4c3b1c24        cmp     r11,qword ptr [rsp]
00007ffe`f0bd26f7 0f85a3e40300    jne     USER32!_guard_ss_verify_failure (00007ffe`f0c10ba0)
00007ffe`f0bd26fd 48ff25dc760900  jmp     qword ptr [USER32!_imp_NtUserGetThreadState (00007ffe`f0c69de0)]


dramatic differences ! it seems that this code has some compiler support and changes in kernel

понедельник, 14 марта 2016 г.

W32pServiceTable from windows 10 build 14279 64bit

W32pServiceLimit .eq. 0x47D

apisetschema.dll from windows 10 build 14279

Several new modules was added:
  • onecoreuap-print-render
  • onecoreuap-settingsync-status
  • win-core-ums
  • win-gdi-internal-uap
  • net-eap-sim
  • win-audiocore-coreaudiopolicymanager
  • win-casting-shell
  • win-com-psmregister
  • win-desktopappx
  • win-direct2d-desktop
  • win-dx-ddraw
  • win-gaming-xinput
  • win-kernelbase-packagebreakaway
  • win-media-avi
  •  win-mf-vfw
  • win-ntuser-private
  • win-rtcore-ntuser-wmpointer
  • win-security-shutdownext
  • win-uwf-servicing-apis

четверг, 3 марта 2016 г.

lxcore syscall table

I can`t get symbols for lxcore.sys so I just write simple idc scipt. Each item in table has very simple structure:
PAGE:00000001C0046620   imul  r14, r12, 38h      ; size of item in syscall table
PAGE:00000001C0046624   mov   r15, rax
PAGE:00000001C0046627   lea   rax, lx_ssdt
PAGE:00000001C004662E   add   r14, rax
PAGE:00000001C0046631   cmp   r12, 136h          ; count of items in syscall table
PAGE:00000001C0046638   jnb   loc_1C00467AE

string with name of method and arguments located at offset 0x10
IDC script to dump syscall table from lxcore.sys:
#include <idc.idc>

static main(void)
{
  auto addr, name, fp, idx, s_addr;
  fp = fopen("lx.dmp", "w");
  if ( !fp )
  {
    return;
  }
  addr = 0x1C0008110;
  for ( idx = 0; idx < 0x136; idx = idx + 1, addr = addr + 0x38 )
  {
    s_addr = Qword(addr + 0x10);
    fprintf(fp, "%X\t", idx);
    if ( s_addr != 0 )
    {
      // dump string
      for ( ; ; s_addr = s_addr + 1 )
      {
        name = Byte(s_addr);
        if ( !name )
          break;
        fprintf(fp, "%c", name);
      }
    }
    fprintf(fp, "\n");
  }
  fclose(fp);
}

And table itself