Closed 0xGotcha closed 11 months ago
Tutorials and other walkthrough are welcome. having a hard time finding information.
Hi 0xGotcha - happy to hear you are interested in cape's debugger, perhaps its most powerful weapon. However you highlight the lack of documentation or tutorials. I have not yet made this type of material, it is long overdue. There is now such a huge subject to cover... But as this is something that will require a lot of time and work, the best I can do is try to give you a quick run through here.
But Guloader is not a good example as it is perhaps one of the biggest challenges capemon has overcome, and the current versions are not working so I need to revisit this loader! It's on my to-do list even higher than the documentation!
So let's use a simpler example, of course I loved the sound of your Ludus, training school for debugger gladiators. Let's trace the hardware breakpoint detection code whilst using.... hardware breakpoints!
A quick yara sig from this code might be:
rule Ludus
{
meta:
cape_options = "bp0=$hwbp"
strings:
$hwbp = {74 7A 48 83 BC 24 88 00 00 00 00 75 37 48 83 BC 24 90 00 00 00 00 75 2C 48 83 BC 24 98 00 00 00 00 75 21 48 83 BC 24 A0 00 00 00 00 75 16 48 83 BC 24 A8 00 00 00 00 75 0B 48 83 BC 24 B0 00 00 00 00 74 38}
condition:
uint16(0) == 0x5A4D and all of them
}
Here we just use the fairly distinct bytes in the drx comparisons to set our hardware breakpoint with bp0=$hwbp
CAPE Sandbox - Debugger log: Tue Nov 21 12:40:59 2023
Breakpoint 0 hit by instruction at 0x00007FF7DF1863D9 (thread 1316) RAX=0x1 RBX=0x178e5bdfbb0 "HardwareDebugRegisters" RCX=0x6f27ab416a970000 RDX=0x178e74f0000 RDI=0x7 RSP=0x4c444fed50 *RSP=0 R8=0xffffffff R9=0x1 R10=0x178e74f0000 R11=0x4c444fe130 R12=0x178e5bd72b0 R14=0xe R15=0x178e5bd72c0 "x" Xmm0.Low=0x3412000000 Xmm1.Low=0x521200007ffc481c Xmm1.High=0x7ff7df1863d700
Break at 0x00007FF7DF1863D9 in 51d003e5a44a9bab864434e0.exe (RVA 0x63d9, thread 1316, ImageBase 0x00007FF7DF180000)
0x00007FF7DF1863D9 747A JZ 0x7c
0x00007FF7DF1863DB 4883BC248800000000 CMP QWORD [RSP+0x88], 0x0
0x00007FF7DF1863E4 7537 JNZ 0x39
0x00007FF7DF1863E6 4883BC249000000000 CMP QWORD [RSP+0x90], 0x0
0x00007FF7DF1863EF 752C JNZ 0x2e
0x00007FF7DF1863F1 4883BC249800000000 CMP QWORD [RSP+0x98], 0x0
0x00007FF7DF1863FA 7521 JNZ 0x23
0x00007FF7DF1863FC 4883BC24A000000000 CMP QWORD [RSP+0xa0], 0x0
0x00007FF7DF186405 7516 JNZ 0x18
0x00007FF7DF186407 4883BC24A800000000 CMP QWORD [RSP+0xa8], 0x0
0x00007FF7DF186410 750B JNZ 0xd
0x00007FF7DF186412 4883BC24B000000000 CMP QWORD [RSP+0xb0], 0x0
0x00007FF7DF18641B 7438 JZ 0x3a
0x00007FF7DF186455 488B8C2410050000 MOV RCX, [RSP+0x510] RCX=0x3d984fd62981
0x00007FF7DF18645D 4833CC XOR RCX, RSP RCX=0x3dd40b99c4d1
0x00007FF7DF186460 E8DB9B0100 CALL 0x00007FF7DF1A0040 RCX=0x3dd40b99c4d10000
0x00007FF7DF186465 4881C428050000 ADD RSP, 0x528 RSP=0x4c444ff278 "*v" *RSP=0x7ff7df18762a
0x00007FF7DF18646C C3 RET
Boom it really is that easy. Here cape cruises past this check because of the defences in the GetThreadContext
hook, but let's imagine that this was actually detecting bp0 with that first jnz
. So we need to 'nop' or skip that instruction so now we set the breakpoint at an offset of 11 to break after the first two instructions with bp0=$hwbp+11
(alternatively we could of course change the yara pattern). We add an action to skip the instruction, and a count to stop tracing immediately.
rule Ludus
{
meta:
cape_options = "bp0=$hwbp+11,action0=skip,count=1"
strings:
$hwbp = {74 7A 48 83 BC 24 88 00 00 00 00 75 37 48 83 BC 24 90 00 00 00 00 75 2C 48 83 BC 24 98 00 00 00 00 75 21 48 83 BC 24 A0 00 00 00 00 75 16 48 83 BC 24 A8 00 00 00 00 75 0B 48 83 BC 24 B0 00 00 00 00 74 38}
condition:
uint16(0) == 0x5A4D and all of them
}
CAPE Sandbox - Debugger log: Tue Nov 21 18:37:28 2023
Breakpoint 0 hit by instruction at 0x00007FF77CC663E4 (thread 7200) RAX=0x1 RBX=0x1ef9c34fff0 "HardwareDebugRegisters" RCX=0x2b5029c0b2d50000 RDX=0x1ef9dd60000 RDI=0x7 RSP=0x902a8ff050 *RSP=0 R8=0xffffffff R9=0x1 R10=0x1ef9dd60000 R11=0x902a8fe430 R12=0x1ef9c350b90 R14=0xe R15=0x1ef9c350ba0 "x" Xmm0.Low=0x3412000000 Xmm0.High=0x65000000000000 Xmm1.Low=0x521200007ffc481c Xmm1.High=0x7ff77cc663d700
Break at 0x00007FF77CC663E4 in 51d003e5a44a9bab864434e0.exe (RVA 0x63e4, thread 7200, ImageBase 0x00007FF77CC60000)
0x00007FF77CC663E4 7537 JNZ 0x39
ActionDispatcher: skipping instruction.
0x00007FF77CC663E6 4883BC249000000000 CMP QWORD [RSP+0x90], 0x0
Trace: Single-step limit reached (1), releasing.
Hey presto, we have a 'bypass' that would force the breakpoint to remain undetected! I hope that helps.
I am interested in testing Yara rules that involve the debugging. Is there any specific technique or development path you follow to test the yara debugging rules? Example would be GuLoader.