Skip to content

Commit

Permalink
add xrefs serach logic + code to find CrashdmpCallTable as POC
Browse files Browse the repository at this point in the history
  • Loading branch information
redplait committed Jun 30, 2020
1 parent 7157234 commit c5b92cf
Show file tree
Hide file tree
Showing 5 changed files with 209 additions and 1 deletion.
93 changes: 93 additions & 0 deletions ldr/hack.h
Expand Up @@ -62,6 +62,99 @@ class regs_pad
reg64_t m_regs[AD_REG_SP];
};

// for xrefs search
struct adr_holder
{
PBYTE addr;
PBYTE where;
inline void reset()
{
addr = where = NULL;
}
adr_holder()
{
reset();
}
};

class xref_finder
{
public:
xref_finder()
{
reset();
}
void reset()
{
for ( DWORD i = 0; i < _countof(m_regs); i++ )
m_regs[i].reset();
disasm_cnt = adrp_cnt = add_cnt = 0;
}
int purge(int i, PBYTE addr)
{
if ( NULL == m_regs[i].where )
return 0;
// 40 - 10 opcodes
if ( m_regs[i].where > addr - 40 )
return 1;
m_regs[i].reset();
return 0;
}
PBYTE find(PBYTE start, DWORD size, PBYTE what)
{
size &= ~3;
struct ad_insn dis;
int reg_n;
for ( DWORD i = 0; i < size / sizeof(DWORD); i++, start += 4 )
{
DWORD val = *(PDWORD)start;
// check for adrp
if ( (val & 0x9f000000) == 0x90000000 )
{
if ( ArmadilloDisassemble(val, (ULONGLONG)start, &dis) )
continue;
disasm_cnt++;
if ( dis.instr_id != AD_INSTR_ADRP )
continue;
adrp_cnt++;
reg_n = dis.operands[0].op_reg.rn;
if ( reg_n >= AD_REG_SP )
continue;
m_regs[reg_n].addr = (PBYTE)dis.operands[1].op_imm.bits;
if ( m_regs[reg_n].addr == what )
return start;
m_regs[reg_n].where = start;
continue;
}
// check for add
if ( (val & 0x7f000000) == 0x11000000 )
{
if ( ArmadilloDisassemble(val, (ULONGLONG)start, &dis) )
continue;
disasm_cnt++;
if ( dis.instr_id != AD_INSTR_ADD )
continue;
add_cnt++;
reg_n = dis.operands[1].op_reg.rn;
if ( reg_n >= AD_REG_SP )
continue;
if ( !purge(reg_n, start) )
continue;
if ( NULL == m_regs[reg_n].addr )
continue;
if ( m_regs[reg_n].addr + (reg64_t)dis.operands[2].op_imm.bits == what )
return start;
}
}
return NULL;
}
DWORD disasm_cnt;
DWORD adrp_cnt;
DWORD add_cnt;
protected:
adr_holder m_regs[AD_REG_SP];
};

// some base class for all hacks
class arm64_hack
{
Expand Down
103 changes: 103 additions & 0 deletions ldr/krnl_crsh.cpp
@@ -0,0 +1,103 @@
#include "stdafx.h"
#include "krnl_hack.h"
#include "bm_search.h"
#include "cf_graph.h"

int ntoskrnl_hack::find_crash_tab(PBYTE mz)
{
const one_section *s = m_pe->find_section_by_name(".text");
if ( NULL == s )
return 0;
PBYTE curr = mz + s->va;
PBYTE end = curr + s->size;
const wchar_t *crash_name = L"\\SystemRoot\\System32\\Drivers\\crashdmp.sys";
size_t b_size = sizeof(wchar_t) * wcslen(crash_name);
bm_search srch((const PBYTE)crash_name, b_size);
std::list<PBYTE> founds;
while ( curr < end )
{
const PBYTE fres = srch.search(curr, end - curr);
if ( NULL == fres )
break;
try
{
founds.push_back(fres);
} catch(std::bad_alloc)
{ return 0; }
curr = fres + b_size;
}
if ( founds.empty() )
return 0;
if ( 1 != founds.size() )
return 0;
PBYTE addr = *(founds.cbegin());
xref_finder xf;
PBYTE res = xf.find(mz + s->va, s->size, addr);
if ( res == NULL )
return 0;
if ( m_verbose )
printf("find_crash_tab: %p %X disasms %X adrp %X add\n", (PBYTE)(res - mz), xf.disasm_cnt, xf.adrp_cnt, xf.add_cnt);
return disasm_crash_tab(res);
}

int ntoskrnl_hack::disasm_crash_tab(PBYTE psp)
{
statefull_graph<PBYTE, int> cgraph;
std::list<std::pair<PBYTE, int> > addr_list;
auto curr = std::make_pair(psp, 0);
addr_list.push_back(curr);
int edge_gen = 0;
int edge_n = 0;
while( edge_gen < 100 )
{
for ( auto iter = addr_list.cbegin(); iter != addr_list.cend(); ++iter )
{
psp = iter->first;
int state = iter->second;
if ( m_verbose )
printf("disasm_crash_tab: %p, state %d, edge_gen %d, edge_n %d\n", psp, state, edge_gen, edge_n);
if ( cgraph.in_ranges(psp) )
continue;
if ( !setup(psp) )
continue;
regs_pad used_regs;
for ( ; ; )
{
if ( !disasm(state) || is_ret() )
break;
if ( check_jmps(cgraph, state) )
continue;
if ( state && is_adrp(used_regs) )
continue;
if ( state && is_add() )
{
PBYTE what = (PBYTE)used_regs.add(get_reg(0), get_reg(1), m_dis.operands[2].op_imm.bits);
if ( !in_section(what, ".data") )
used_regs.zero(get_reg(0));
continue;
}
PBYTE addr = NULL;
if ( is_bl_jimm(addr) )
{
if ( addr == aux_RtlImageNtHeader )
{
state = 1;
continue;
}
if ( state && (addr == aux_dispatch_icall) )
{
m_CrashdmpCallTable = (PBYTE)used_regs.get(AD_REG_X1);
goto end;
}
}
}
cgraph.add_range(psp, m_psp - psp);
}
// prepare for next edge generation
edge_gen++;
if ( !cgraph.delete_ranges(&cgraph.ranges, &addr_list) )
break;
}
end:
return (m_CrashdmpCallTable != NULL);
}
8 changes: 7 additions & 1 deletion ldr/krnl_hack.cpp
Expand Up @@ -33,9 +33,11 @@ void ntoskrnl_hack::zero_data()
init_aux("ExAllocatePoolWithTag", aux_ExAllocatePoolWithTag);
init_aux("ExEnumHandleTable", aux_ExEnumHandleTable);
init_aux("ExfUnblockPushLock", aux_ExfUnblockPushLock);
init_aux("RtlImageNtHeader", aux_RtlImageNtHeader);
init_aux("PsInitialSystemProcess", aux_PsInitialSystemProcess);
aux_ExAllocateCallBack = aux_ExCompareExchangeCallBack = aux_dispatch_icall = NULL;
// zero output data
m_CrashdmpCallTable = NULL;
m_PspSiloMonitorLock = m_PspSiloMonitorList = NULL;
m_WmipGuidObjectType = m_WmipRegistrationSpinLock = m_WmipInUseRegEntryHead = NULL;
m_MiGetPteAddress = m_pte_base_addr = NULL;
Expand Down Expand Up @@ -66,6 +68,8 @@ void ntoskrnl_hack::dump() const
PBYTE mz = m_pe->base_addr();
if ( aux_dispatch_icall != NULL )
printf("guard_dispatch_icall: %p\n", PVOID(aux_dispatch_icall - mz));
if ( m_CrashdmpCallTable != NULL )
printf("CrashdmpCallTable: %p\n", PVOID(m_CrashdmpCallTable - mz));
// lookaside lists & locks
if ( m_ExNPagedLookasideLock != NULL )
printf("ExNPagedLookasideLock: %p\n", PVOID(m_ExNPagedLookasideLock - mz));
Expand Down Expand Up @@ -185,7 +189,9 @@ int ntoskrnl_hack::hack(int verbose)
// first resolve guard_dispatch_icall
const export_item *exp = m_ed->find("RtlGetCompressionWorkSpaceSize");
if ( exp != NULL )
res += find_first_jmp(mz + exp->rva, aux_dispatch_icall);
res += find_first_jmp(mz + exp->rva, aux_dispatch_icall);
if ( aux_dispatch_icall != NULL )
res += find_crash_tab(mz);
// lookaside lists & locks
exp = m_ed->find("ExInitializePagedLookasideList");
if ( exp != NULL )
Expand Down
5 changes: 5 additions & 0 deletions ldr/krnl_hack.h
Expand Up @@ -50,6 +50,8 @@ class ntoskrnl_hack: public arm64_hack
int disasm_IoWMIDeviceObjectToProviderId(PBYTE, PBYTE &);
int disasm_WmipDoFindRegEntryByDevice(PBYTE);
int hack_start_silo(PBYTE);
int find_crash_tab(PBYTE mz);
int disasm_crash_tab(PBYTE);
// auxilary data
PBYTE aux_MmUserProbeAddress;
PBYTE aux_MmSystemRangeStart;
Expand All @@ -68,6 +70,7 @@ class ntoskrnl_hack: public arm64_hack
PBYTE aux_memset;
PBYTE aux_ExEnumHandleTable;
PBYTE aux_ExfUnblockPushLock;
PBYTE aux_RtlImageNtHeader;
PBYTE aux_PsInitialSystemProcess;
// not exported
PBYTE aux_ExAllocateCallBack;
Expand Down Expand Up @@ -96,6 +99,8 @@ class ntoskrnl_hack: public arm64_hack
// extensions
PBYTE m_ExpHostListLock;
PBYTE m_ExpHostList; // from ExpFindHost
// CrashdmpCallTable
PBYTE m_CrashdmpCallTable;
// kernel notificators
PBYTE m_PsWin32CallBack;
PBYTE m_SepRmNotifyMutex;
Expand Down
1 change: 1 addition & 0 deletions ldr/ldr.vcxproj
Expand Up @@ -160,6 +160,7 @@
<ClCompile Include="exports_dict.cpp" />
<ClCompile Include="hack.cpp" />
<ClCompile Include="imports_dict.cpp" />
<ClCompile Include="krnl_crsh.cpp" />
<ClCompile Include="krnl_hack.cpp" />
<ClCompile Include="krnl_obtypes.cpp" />
<ClCompile Include="krnl_pnp.cpp" />
Expand Down

0 comments on commit c5b92cf

Please sign in to comment.