|
| 1 | +using namespace System.ComponentModel |
| 2 | +using namespace System.Diagnostics |
| 3 | +using namespace System.Runtime.InteropServices |
| 4 | + |
| 5 | +# Windows x64 |
| 6 | +# int(int* args, int count) |
| 7 | +# { |
| 8 | +# int total = 0; |
| 9 | +# for (int i = 0; i < count; i++) |
| 10 | +# { |
| 11 | +# total += args[i]; |
| 12 | +# } |
| 13 | +# |
| 14 | +# return total; |
| 15 | +# } |
| 16 | +$assembly = ( |
| 17 | + 0x85, 0xD2, # test edx,edx |
| 18 | + 0x7E, 0x14, # jle 18 <LBB0_1> |
| 19 | + 0x41, 0x89, 0xD0, # mov r8d,edx |
| 20 | + 0x31, 0xD2, # xor edx,edx |
| 21 | + 0x31, 0xC0, # xor eax,eax |
| 22 | +# LBB0_4: |
| 23 | + 0x03, 0x04, 0x91, # add eax,DWORD PTR [rcx+rdx*4] |
| 24 | + 0x48, 0x83, 0xC2, 0x01, # add rdx,0x1 |
| 25 | + 0x49, 0x39, 0xD0, # cmp r8,rdx |
| 26 | + 0x75, 0xF4, # jne b <LBB0_4> |
| 27 | + 0xC3, # ret |
| 28 | +# LBB0_1 |
| 29 | + 0x31, 0xC0, # xor eax,eax |
| 30 | + 0xC3 # ret |
| 31 | +) |
| 32 | + |
| 33 | +$delegate = il { [int]([byte[]] $asm, [int[]] $args) } { |
| 34 | + .locals init { |
| 35 | + [void+] $virtualProtectEx, |
| 36 | + |
| 37 | + [void+] $getLastError, |
| 38 | + |
| 39 | + [uint] $flOldProtect, |
| 40 | + |
| 41 | + [pinned] [byte[]] $pinnedAsm, |
| 42 | + |
| 43 | + [pinned] [int[]] $pinnedArgs |
| 44 | + } |
| 45 | + |
| 46 | + # [DllImport("kernel32")] |
| 47 | + # static extern int VirtualProtectEx(void*, void*, int, int, int*) |
| 48 | + ldstr 'kernel32' |
| 49 | + call { [IntPtr] [NativeLibrary]::Load([string]) } |
| 50 | + dup |
| 51 | + ldstr 'VirtualProtectEx' |
| 52 | + call { [IntPtr] [NativeLibrary]::GetExport([IntPtr], [string]) } |
| 53 | + stloc.auto $virtualProtectEx |
| 54 | + |
| 55 | + # [DllImport("kernel32")] |
| 56 | + # static extern int GetLastError() |
| 57 | + ldstr 'GetLastError' |
| 58 | + call { [IntPtr] [NativeLibrary]::GetExport([IntPtr], [string]) } |
| 59 | + stloc.auto $getLastError |
| 60 | + |
| 61 | + # pinnedAsm = asm |
| 62 | + ldarg.0 |
| 63 | + stloc.auto $pinnedAsm |
| 64 | + |
| 65 | + # Process.GetCurrentProcess().Handle |
| 66 | + call { [Process] [Process]::GetCurrentProcess() } |
| 67 | + callvirt { [IntPtr] [Process].get_Handle() } |
| 68 | + # &pinnedAsm[0] |
| 69 | + ldloc.auto $pinnedAsm |
| 70 | + ldc.i4.0 |
| 71 | + ldelema { [byte] } |
| 72 | + # pinnedAsm.Length |
| 73 | + ldloc.auto $pinnedAsm |
| 74 | + ldlen |
| 75 | + # 0x40 |
| 76 | + ldc.i4.s 0x40 |
| 77 | + # &flOldProtect |
| 78 | + ldloca.auto $flOldProtect |
| 79 | + |
| 80 | + # VirtualProtectEx(Process.GetCurrentProcess().Handle, &pinnedAsm[0], pinnedAsm.Length, 0x40, &flOldProtect) |
| 81 | + ldloc.auto $virtualProtectEx |
| 82 | + calli unmanaged stdcall { [int]([void+], [void+], [int], [int], [int+]) } |
| 83 | + |
| 84 | + # if (vpResult != 0) goto success |
| 85 | + brtrue.s success |
| 86 | + |
| 87 | + # throw new Win32Exception(GetLastError()) |
| 88 | + ldloc.auto $getLastError |
| 89 | + calli unmanaged stdcall { [int]@() } |
| 90 | + newobj { [void] [Win32Exception].new([int]) } |
| 91 | + throw |
| 92 | + |
| 93 | +success: |
| 94 | + |
| 95 | + # pinnedArgs = args |
| 96 | + ldarg.1 |
| 97 | + stloc.auto $pinnedArgs |
| 98 | + |
| 99 | + # &pinnedArgs[0] |
| 100 | + ldloc.auto $pinnedArgs |
| 101 | + ldc.i4.0 |
| 102 | + ldelema { [int] } |
| 103 | + # pinnedArgs.Length |
| 104 | + ldloc.auto $pinnedArgs |
| 105 | + ldlen |
| 106 | + # &pinnedAsm[0] |
| 107 | + ldloc.auto $pinnedAsm |
| 108 | + ldc.i4.0 |
| 109 | + ldelema { [byte] } |
| 110 | + |
| 111 | + # return ((delegate* unmanaged[Stdcall]<int*, int, int>)&pinnedAsm[0])(&pinnedArgs[0], pinnedArgs.Length) |
| 112 | + calli unmanaged stdcall { [int]([int+], [int]) } |
| 113 | + ret |
| 114 | +} |
| 115 | + |
| 116 | +$delegate.Invoke($assembly, @(20, 60, 324)) |
| 117 | +# returns: 404 |
0 commit comments