WinExec 抛出 EXCEPTION_ACCESS_VIOLATION

问题描述 投票:0回答:1

我尝试修改 this shellcode 并使其运行 notepad.exe 而不是 calc.exe。我正在使用此代码片段将 notepad.exe 放入堆栈中

push

mov r9, 0x0000000000657865 push r9 mov r9, 0x2e64617065746f6e push r9

ing

CALL
时,
WinExec
寄存器指向
RCX
字符串。

但进入 kernel32.dll notepad.exe后会抛出异常。

这是完整的shellcode代码

EXCEPTION_ACCESS_VIOLATION

唯一的修改是我按下 
BITS 64 SECTION .text %define B2W(b1,b2) (((b2) << 8) + (b1)) %define W2DW(w1,w2) (((w2) << 16) + (w1)) %define DW2QW(dw1,dw2) (((dw2) << 32) + (dw1)) %define B2DW(b1,b2,b3,b4) ((B2W(b3, b4) << 16) + B2W(b1, b2)) %define B2QW(b1,b2,b3,b4,b5,b6,b7,b8) ((B2DW(b5,b6,b7,b8) << 32) + B2DW(b1,b2,b3,b4)) %define W2QW(w1,w2,w3,w4) ((W2DW(w3,w4) << 32) + W2DW(w1,w2)) ; x64 WinExec *requires* 16 byte stack alignment and four QWORDS of stack space, which may be overwritten. ; http://msdn.microsoft.com/en-us/library/ms235286.aspx %ifndef PLATFORM_INDEPENDENT global shellcode shellcode: %ifdef FUNC ; assumes stack ends with 8 on entry, use STACK_ALIGN if it might not be. %ifdef CLEAN ; 64-bit calling convention considers RAX, RCX, RDX, R8, R9, R10 and R11 PUSH RAX ; volatile. Use CLEAN if you want to preserve those as well. PUSH RCX PUSH RDX %endif PUSH RBX PUSH RSI PUSH RDI PUSH RBP ; Stack now ends with 8 (!CLEAN) or is 16 byte (CLEAN) aligned %endif %ifdef STACK_ALIGN %ifdef FUNC PUSH RSP POP RAX %endif AND SP, -16 ; Align stack to 16 bytes ; (we can't force it to end with 8 without dummy push and then or) PUSH RAX ; Force stack to end with 8 before next push, also saves RSP to restore stack %elifdef CLEAN PUSH RAX ; dummy push to make stack end with 8 before next push %endif ; Note to SkyLined: instructions on 32-bit registers are automatically sign-extended to 64-bits. ; This means LODSD will set the high DWORD of RAX to 0 if top bit of EAX was 0, or 0xFFFFFFFF if it was 0x80000000. PUSH BYTE 0x60 ; Stack POP RDX ; RDX = 0x60 %else %ifdef FUNC %ifdef CLEAN PUSH RAX ; exchanged RDX PUSH RCX %endif PUSH RBX PUSH RSI PUSH RDI PUSH RBP ; Stack now ends with 8 (!CLEAN) or is 16 byte (CLEAN) aligned %endif %ifdef CLEAN %ifndef STACK_ALIGN PUSH RAX ; dummy push to make stack end with 8 before next push %endif %endif MOV DL, 0x60 %endif %ifndef USE_COMMON ;PUSH B2DW('c', 'a', 'l', 'c') ; Stack = "calc\0\0\0\0" (stack alignment changes) mov r9, 0x0000000000657865 push r9 mov r9, 0x2e64617065746f6e push r9 PUSH RSP POP RCX ; RCX = &("calc") %endif SUB RSP, RDX ; Stack was 16 byte aligned already and there are >4 QWORDS on the stack. MOV RSI, [GS:RDX] ; RSI = [TEB + 0x60] = &PEB MOV RSI, [RSI + 0x18] ; RSI = [PEB + 0x18] = PEB_LDR_DATA MOV RSI, [RSI + 0x10] ; RSI = [PEB_LDR_DATA + 0x10] = LDR_MODULE InLoadOrder[0] (process) LODSQ ; RAX = InLoadOrder[1] (ntdll) MOV RSI, [RAX] ; RSI = InLoadOrder[2] (kernel32) MOV RDI, [RSI + 0x30] ; RDI = [InLoadOrder[2] + 0x30] = kernel32 DllBase ; Found kernel32 base address (RDI) shellcode_common: ADD EDX, DWORD [RDI + 0x3C] ; RBX = 0x60 + [kernel32 + 0x3C] = offset(PE header) + 0x60 ; PE header (RDI+RDX-0x60) = @0x00 0x04 byte signature ; @0x04 0x18 byte COFF header ; @0x18 PE32 optional header (= RDI + RDX - 0x60 + 0x18) MOV EBX, DWORD [RDI + RDX - 0x60 + 0x18 + 0x70] ; RBX = [PE32+ optional header + offset(PE32+ export table offset)] = offset(export table) ; Export table (RDI+EBX) = @0x20 Name Pointer RVA MOV ESI, DWORD [RDI + RBX + 0x20] ; RSI = [kernel32 + offset(export table) + 0x20] = offset(names table) ADD RSI, RDI ; RSI = kernel32 + offset(names table) = &(names table) ; Found export names table (RSI) MOV EDX, DWORD [RDI + RBX + 0x24] ; EDX = [kernel32 + offset(export table) + 0x24] = offset(ordinals table) ; Found export ordinals table (RDX) find_winexec_x64: ; speculatively load ordinal (RBP) MOVZX EBP, WORD [RDI + RDX] ; RBP = [kernel32 + offset(ordinals table) + offset] = function ordinal LEA EDX, [RDX + 2] ; RDX = offset += 2 (will wrap if > 4Gb, but this should never happen) LODSD ; RAX = &(names table[function number]) = offset(function name) CMP DWORD [RDI + RAX], B2DW('W', 'i', 'n', 'E') ; *(DWORD*)(function name) == "WinE" ? JNE find_winexec_x64 ; MOV ESI, DWORD [RDI + RBX + 0x1C] ; RSI = [kernel32 + offset(export table) + 0x1C] = offset(address table) ADD RSI, RDI ; RSI = kernel32 + offset(address table) = &(address table) MOV ESI, [RSI + RBP * 4] ; RSI = &(address table)[WinExec ordinal] = offset(WinExec) ADD RDI, RSI ; RDI = kernel32 + offset(WinExec) = WinExec ; Found WinExec (RDI) CDQ ; RDX = 0 (assuming EAX < 0x80000000, which should always be true) CALL RDI ; WinExec(&("calc"), 0); %ifdef FUNC %ifdef CLEAN %ifdef STACK_ALIGN ADD RSP, 0x68 ; reset stack to where it was after pushing registers %else ADD RSP, 0x70 ; reset stack to where it was after pushing registers %endif %else ADD RSP, 0x68 ; reset stack to where it was after pushing registers %endif %ifndef PLATFORM_INDEPENDENT %ifdef STACK_ALIGN POP RSP %endif %endif POP RBP ; POP registers POP RDI POP RSI POP RBX %ifndef PLATFORM_INDEPENDENT %ifdef CLEAN POP RDX ; POP additional registers POP RCX POP RAX %endif RET ; Return %else %ifdef CLEAN POP RCX ; POP additional registers POP RDX %endif %ifdef STACK_ALIGN POP RSP %endif %ifdef CLEAN POP RAX %endif RET ; Return %endif %endif

而不是

notepad.exe
。 我不明白为什么抛出异常以及如何修复它。
Shellcode 被组装并链接到

calc.exe


assembly nasm
1个回答
0
投票
唯一的修改是我按下
nasm -fwin64 w64-exec-calc-shellcode.asm -o mybuilds\exe\x64-exec-calc-shellcode.obj link /MACHINE:x64 /SUBSYSTEM:CONSOLE /OUT:mybuilds\exe\x64-exec-calc-shellcode.exe /NODEFAULTLIB /ENTRY:shellcode kernel32.lib mybuilds\exe\x64-exec-calc-shellcode.obj

而不是

notepad.exe

你为什么要包括
calc.exe


.exe
我没有看到原始版本已将 
;PUSH B2DW('c', 'a', 'l', 'c') ; Stack = "calc\0\0\0\0" (stack alignment changes) mov r9, 0x0000000000657865 push r9 mov r9, 0x2e64617065746f6e push r9 PUSH RSP POP RCX ; RCX = &("calc")

添加到

.exe
,如果该版本工作正常,则这样做:
calc

© www.soinside.com 2019 - 2024. All rights reserved.