Skip to content

Commit 42d5670

Browse files
committed
LdrLoadDll
1 parent 50a78f2 commit 42d5670

File tree

5 files changed

+153
-6
lines changed

5 files changed

+153
-6
lines changed

README.md

+14-2
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,14 @@ x86 32bits emulator, for securely emulating shellcodes
55
- rust speed, 18,750 instructions per second
66
- iteration detector
77
- colorized
8-
- stop at sepcific moment and explore the state or modify it.
9-
- 73 instructions implemented
8+
- stop at specific moment and explore the state or modify it.
9+
- 90 instructions implemented
10+
- SEH chains
11+
- vectored exception handler
12+
- int3
13+
- non debugged cpuid
14+
15+
1016

1117

1218
Some use cases:
@@ -19,3 +25,9 @@ We select the line to stop and inspect the memory
1925

2026
After emulating near 2 million instructions of GuLoader win32 in linux, faking cpuid's and other tricks in the way, arrives to a sigtrap to confuse debuggers.
2127
![exception handlers](pics/guloader1.png)
28+
29+
Example of memory dump on the api loader
30+
![exception handlers](pics/memdump.png)
31+
32+
There are several maps by default, and can be created more with apis like LoadLibraryA or manually from the console:
33+
![exception handlers](pics/maps.png)

pics/maps.png

30.1 KB
Loading

pics/memdump.png

39.5 KB
Loading

src/emu32.rs

+136-1
Original file line numberDiff line numberDiff line change
@@ -888,7 +888,7 @@ impl Emu32 {
888888
self.exp = num;
889889
return;
890890
},
891-
"s" => self.maps.get_mem("stack").print_dwords_from_to(self.regs.esp, self.regs.ebp),
891+
"s" => self.maps.get_mem("stack").print_dwords_from_to(self.regs.esp, self.regs.esp+48),
892892
"v" => self.maps.get_mem("stack").print_dwords_from_to(self.regs.ebp, self.regs.ebp+0x100),
893893
"c" => return,
894894
"f" => self.flags.print(),
@@ -1014,6 +1014,7 @@ impl Emu32 {
10141014
0x775b52d8 => self.ntdll_NtAllocateVirtualMemory(),
10151015
0x775b5a18 => self.ntdll_NtGetContextThread(),
10161016
0x7757f774 => self.ntdll_RtlVectoredExceptionHandler(),
1017+
0x775d22b8 => self.ntdll_LdrLoadDll(),
10171018
_ => panic!("calling unknown ntdll API 0x{:x}", addr),
10181019
}
10191020
}
@@ -1027,6 +1028,24 @@ impl Emu32 {
10271028
_ => panic!("calling unknown kernel32 API 0x{:x}", addr),
10281029
}
10291030
}
1031+
1032+
fn ntdll_LdrLoadDll(&mut self) {
1033+
let libptr = match self.maps.read_dword(self.regs.esp+20) {
1034+
Some(v) => v,
1035+
None => panic!("LdrLoadDll: error reading lib param")
1036+
};
1037+
1038+
let lib = self.maps.read_wide_string(libptr);
1039+
1040+
let colors = Colors::new();
1041+
println!("{}** ntdll_LdrLoadDll lib:{} {}",colors.light_red, lib, colors.nc);
1042+
1043+
1044+
for _ in 0..4 {
1045+
self.stack_pop(false);
1046+
}
1047+
self.regs.eax = constants::STATUS_SUCCESS;
1048+
}
10301049

10311050
fn ntdll_RtlVectoredExceptionHandler(&mut self) {
10321051
let p1 = match self.maps.read_dword(self.regs.esp) {
@@ -1039,6 +1058,9 @@ impl Emu32 {
10391058
None => panic!("ntdll_RtlVectoredExceptionHandler: error reading fptr"),
10401059
};
10411060

1061+
let colors = Colors::new();
1062+
println!("{}** ntdll_RtlVectoredExceptionHandler callback:0x{:x} {}",colors.light_red, fptr, colors.nc);
1063+
10421064
self.vseh = fptr;
10431065

10441066
self.regs.eax = 0x2c2878;
@@ -5094,6 +5116,9 @@ impl Emu32 {
50945116
},
50955117

50965118
Some("leave") => {
5119+
if !step {
5120+
println!("{}{} {}{}", colors.red, pos, ins, colors.nc);
5121+
}
50975122
self.regs.esp = self.regs.ebp;
50985123
self.regs.ebp = self.stack_pop(true);
50995124
},
@@ -5125,6 +5150,9 @@ impl Emu32 {
51255150

51265151
Some("lock btr") => {
51275152
// 747712 0x775b77b2: lock btr dword ptr [eax], 0
5153+
if !step {
5154+
println!("{}{} {}{}", colors.blue, pos, ins, colors.nc);
5155+
}
51285156
let op = ins.op_str().unwrap();
51295157
let parts:Vec<&str> = op.split(", ").collect();
51305158
let bit_off = self.get_inmediate(parts[1]);
@@ -5142,6 +5170,9 @@ impl Emu32 {
51425170
},
51435171

51445172
Some("lock cmpxchg") => {
5173+
if !step {
5174+
println!("{}{} {}{}", colors.blue, pos, ins, colors.nc);
5175+
}
51455176
// 747743 0x775a229a: lock cmpxchg dword ptr [ebx], edx
51465177
// compare memory [ebx] with eax if they are same, move edx to [ebx]
51475178
let op = ins.op_str().unwrap();
@@ -5185,6 +5216,110 @@ impl Emu32 {
51855216

51865217
},
51875218

5219+
Some("std") => {
5220+
if !step {
5221+
println!("{}{} {}{}", colors.blue, pos, ins, colors.nc);
5222+
}
5223+
self.flags.f_df = true;
5224+
},
5225+
5226+
Some("cld") => {
5227+
if !step {
5228+
println!("{}{} {}{}", colors.blue, pos, ins, colors.nc);
5229+
}
5230+
self.flags.f_df = false;
5231+
}
5232+
5233+
Some("lodsd") => {
5234+
if !step {
5235+
println!("{}{} {}{}", colors.blue, pos, ins, colors.nc);
5236+
}
5237+
let val = match self.memory_read("dword ptr [esi]") {
5238+
Some(v) => v,
5239+
None => panic!("lodsw: memory read error")
5240+
};
5241+
self.regs.eax = val;
5242+
if self.flags.f_df {
5243+
self.regs.esi -= 4;
5244+
} else {
5245+
self.regs.esi += 4;
5246+
}
5247+
},
5248+
5249+
Some("lodsw") => {
5250+
if !step {
5251+
println!("{}{} {}{}", colors.blue, pos, ins, colors.nc);
5252+
}
5253+
let val = match self.memory_read("word ptr [esi]") {
5254+
Some(v) => v,
5255+
None => panic!("lodsw: memory read error")
5256+
};
5257+
self.regs.set_ax(val);
5258+
if self.flags.f_df {
5259+
self.regs.esi -= 2;
5260+
} else {
5261+
self.regs.esi += 2;
5262+
}
5263+
},
5264+
5265+
Some("lodsb") => {
5266+
if !step {
5267+
println!("{}{} {}{}", colors.blue, pos, ins, colors.nc);
5268+
}
5269+
let val = match self.memory_read("byte ptr [esi]") {
5270+
Some(v) => v,
5271+
None => panic!("lodsw: memory read error")
5272+
};
5273+
self.regs.set_al(val);
5274+
if self.flags.f_df {
5275+
self.regs.esi -= 1;
5276+
} else {
5277+
self.regs.esi += 1;
5278+
}
5279+
},
5280+
5281+
Some("lods") => {
5282+
if !step {
5283+
println!("{}{} {}{}", colors.blue, pos, ins, colors.nc);
5284+
}
5285+
5286+
let op = ins.op_str().unwrap();
5287+
let bits = self.get_size(op);
5288+
let val = match self.memory_read(op) {
5289+
Some(v) => v,
5290+
None => panic!("lodsw: memory read error")
5291+
};
5292+
5293+
match bits {
5294+
32 => {
5295+
self.regs.eax = val;
5296+
if self.flags.f_df {
5297+
self.regs.esi -= 4;
5298+
} else {
5299+
self.regs.esi += 4;
5300+
}
5301+
},
5302+
16 => {
5303+
self.regs.set_ax(val);
5304+
if self.flags.f_df {
5305+
self.regs.esi -= 2;
5306+
} else {
5307+
self.regs.esi += 2;
5308+
}
5309+
},
5310+
8 => {
5311+
self.regs.set_al(val);
5312+
if self.flags.f_df {
5313+
self.regs.esi -= 1;
5314+
} else {
5315+
self.regs.esi += 1;
5316+
}
5317+
},
5318+
_ => panic!("bad precision"),
5319+
}
5320+
},
5321+
5322+
51885323
Some("sysenter") => {
51895324
println!("{}{} {}{} function: 0x{:x}", colors.red, pos, ins, colors.nc, self.regs.eax);
51905325
return;

src/main.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,11 @@ fn main() {
2929

3030
let mode = &args[2];
3131

32-
if mode == "quick" {
32+
if mode == "q" {
3333
emu32.mode_quick();
34-
} else if mode == "loop" {
34+
} else if mode == "l" {
3535
emu32.mode_loop();
36-
} else if mode == "regs" {
36+
} else if mode == "r" {
3737
emu32.mode_regs();
3838
}
3939

0 commit comments

Comments
 (0)