Skip to content

Commit bb77903

Browse files
committed
support for metasploit encoder
1 parent a8205f3 commit bb77903

File tree

4 files changed

+98
-11
lines changed

4 files changed

+98
-11
lines changed

README.md

+20-4
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,37 @@
11
# scemu
22
x86 32bits emulator, for securely emulating shellcodes
33

4+
## Features
45
- rust safety, good for malware.
56
- rust speed, ~10,000 instructions per second
67
- iteration detector
78
- colorized
89
- stop at specific moment and explore the state or modify it.
9-
- 90 instructions implemented
10+
- 92 instructions implemented
1011
- 39 winapi implemented of 5 dlls
1112
- SEH chains
1213
- vectored exception handler
1314
- int3
1415
- non debugged cpuid
1516
- zero unsafe{} blocks
16-
17-
Usage:
17+
- tests with known payloads:
18+
- metasploit shellcodes
19+
- metasploit encoder
20+
- cobalt strike
21+
- guloader (not totally for now)
22+
23+
## TODO
24+
- more fpu
25+
- mmx
26+
- 64 bits
27+
- scripting?
28+
- stagers: get next stage
29+
30+
## Usage
1831
![usage](pics/usage.png)
1932

2033

21-
Some use cases:
34+
## Some use cases
2235

2336
scemu emulates a simple shellcode detecting the execve() interrupt.
2437
![exploring basic shellcode](pics/basic_shellcode1.png)
@@ -51,3 +64,6 @@ Cobalt Strike API called:
5164

5265
Metasploit rshell API called:
5366
![msf rshell](pics/metasploit_rshell.png)
67+
68+
Metasploit encoder using few fpu to hide the polymorfism:
69+
![msf encoded](pics/msf_encoded.png)

pics/msf_encoded.png

74.5 KB
Loading

src/emu32.rs

+71-5
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,7 @@ pub struct Emu32 {
175175
cfg: Config,
176176
colors: Colors,
177177
pos: u64,
178+
force_break: bool,
178179
}
179180

180181
impl Emu32 {
@@ -193,6 +194,7 @@ impl Emu32 {
193194
cfg: Config::new(),
194195
colors: Colors::new(),
195196
pos: 0,
197+
force_break: false,
196198
}
197199
}
198200

@@ -755,11 +757,19 @@ impl Emu32 {
755757
panic!("writting in non mapped memory");
756758
}*/
757759

760+
let name = match self.maps.get_addr_name(addr) {
761+
Some(n) => n,
762+
None => "error".to_string(),
763+
};
764+
765+
if name == "code" {
766+
if self.cfg.verbose >= 1 {
767+
println!("/!\\ polymorfic code");
768+
}
769+
self.force_break = true;
770+
}
771+
758772
if self.cfg.trace_mem {
759-
let name = match self.maps.get_addr_name(addr) {
760-
Some(n) => n,
761-
None => "error".to_string(),
762-
};
763773
println!("mem trace write -> '{}' 0x{:x}: 0x{:x} map:'{}'", operand, addr, value, name);
764774
}
765775

@@ -1339,7 +1349,7 @@ impl Emu32 {
13391349
let code = self.maps.get_mem(map_name.as_str());
13401350
let block = code.read_from(eip);
13411351
let insns = cs.disasm_all(block, eip as u64).expect("Failed to disassemble");
1342-
1352+
13431353
for ins in insns.as_ref() {
13441354
//TODO: use InsnDetail https://docs.rs/capstone/0.4.0/capstone/struct.InsnDetail.html
13451355
//let detail: InsnDetail = cs.insn_detail(&ins).expect("Failed to get insn detail");
@@ -5509,6 +5519,57 @@ impl Emu32 {
55095519
self.fpu.set_eip(self.regs.eip);
55105520
},
55115521

5522+
Some("lcall") => {
5523+
if !step {
5524+
panic!("{}{} {} {{{:?}}} {}", self.colors.green, self.pos, ins, ins.bytes(), self.colors.nc);
5525+
}
5526+
/*
5527+
emulated with unicorn as a loop:
5528+
0x1000016: add edx, 4 ebp:0x2801000
5529+
0x1000019: lcall 0x51c0:0xd572a83f ebp:0x2801000
5530+
0x1000010: xor dword ptr [edx + 0x14], ebx ebp:0x2801000
5531+
0x1000013: add ebx, dword ptr [edx + 0x14] ebp:0x2801000
5532+
0x1000016: add edx, 4 ebp:0x2801000
5533+
0x1000019: lcall 0x51c0:0xd572a83f ebp:0x2801000
5534+
0x1000010: xor dword ptr [edx + 0x14], ebx ebp:0x2801000
5535+
0x1000013: add ebx, dword ptr [edx + 0x14] ebp:0x2801000
5536+
0x1000016: add edx, 4 ebp:0x2801000
5537+
0x1000019: lcall 0x51c0:0xd572a83f ebp:0x2801000
5538+
0x1000010: xor dword ptr [edx + 0x14], ebx ebp:0x2801000
5539+
0x1000013: add ebx, dword ptr [edx + 0x14] ebp:0x2801000
5540+
0x1000016: add edx, 4 ebp:0x2801000
5541+
0x1000019: lcall 0x51c0:0xd572a83f ebp:0x2801000
5542+
0x1000010: xor dword ptr [edx + 0x14], ebx ebp:0x2801000
5543+
0x1000013: add ebx, dword ptr [edx + 0x14] ebp:0x2801000
5544+
0x1000016: add edx, 4 ebp:0x2801000
5545+
0x1000019: lcall 0x51c0:0xd572a83f ebp:0x2801000
5546+
0x1000010: xor dword ptr [edx + 0x14], ebx ebp:0x2801000
5547+
0x1000013: add ebx, dword ptr [edx + 0x14] ebp:0x2801000
5548+
0x1000016: add edx, 4 ebp:0x2801000
5549+
0x1000019: lcall 0x51c0:0xd572a83f ebp:0x2801000
5550+
0x1000010: xor dword ptr [edx + 0x14], ebx ebp:0x2801000
5551+
0x1000013: add ebx, dword ptr [edx + 0x14] ebp:0x2801000
5552+
0x1000016: add edx, 4 ebp:0x2801000
5553+
0x1000019: lcall 0x51c0:0xd572a83f ebp:0x2801000
5554+
0x1000010: xor dword ptr [edx + 0x14], ebx ebp:0x2801000
5555+
0x1000013: add ebx, dword ptr [edx + 0x14] ebp:0x2801000
5556+
0x1000016: add edx, 4 ebp:0x2801000
5557+
0x1000019: lcall 0x51c0:0xd572a83f ebp:0x2801000
5558+
0x1000010: xor dword ptr [edx + 0x14], ebx ebp:0x2801000
5559+
0x1000013: add ebx, dword ptr [edx + 0x14] ebp:0x2801000
5560+
0x1000016: add edx, 4 ebp:0x2801000
5561+
0x1000019: lcall 0x51c0:0xd572a83f ebp:0x2801000
5562+
0x1000010: xor dword ptr [edx + 0x14], ebx ebp:0x2801000
5563+
0x1000013: add ebx, dword ptr [edx + 0x14] ebp:0x2801000
5564+
0x1000016: add edx, 4 ebp:0x2801000
5565+
0x1000019: lcall 0x51c0:0xd572a83f ebp:0x2801000
5566+
0x100001b: test al, 0x72 ebp:0x2801000
5567+
0x100001c: jb 0xfffff3 ebp:0x2801000
5568+
5569+
opcodes:
5570+
10 0x3c0019: lcall 0x51c0, 0xd572a83f {[154, 63, 168, 114, 213, 192, 81]}
5571+
*/
5572+
},
55125573

55135574
Some("sysenter") => {
55145575
println!("{}{} {}{} function: 0x{:x}", self.colors.red, self.pos, ins, self.colors.nc, self.regs.eax);
@@ -5519,11 +5580,16 @@ impl Emu32 {
55195580
println!("{}{} {}{}", self.colors.red, self.pos, ins, self.colors.nc);
55205581
panic!("unimplemented instruction");
55215582
},
5583+
55225584
None => panic!("none instruction"),
55235585
}
55245586

55255587
self.regs.eip += sz as u32;
55265588

5589+
if self.force_break {
5590+
self.force_break = false;
5591+
break;
5592+
}
55275593
}
55285594
}
55295595

src/emu32/maps/mem32.rs

+7-2
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,13 @@ impl Mem32 {
6161

6262
pub fn read_from(&self, addr:u32) -> &[u8] {
6363
let idx = (addr - self.base_addr) as usize;
64-
let sz = (self.bottom_addr - self.base_addr) as usize;
65-
return self.mem.get(idx..sz).unwrap();
64+
let max_sz = (self.bottom_addr - self.base_addr) as usize;
65+
/*
66+
let mut sz = idx + 5;
67+
if sz > max_sz {
68+
sz = max_sz;
69+
}*/
70+
return self.mem.get(idx..max_sz).unwrap();
6671
}
6772

6873
pub fn read_bytes(&self, addr:u32, sz:usize) -> &[u8] {

0 commit comments

Comments
 (0)