Skip to content

Commit 5a61798

Browse files
committed
Added new shemu flag: SHEMU_FLAG_SUD_ACCESS is raised whenever the code accesses the SharedUserData page.
1 parent c8735b4 commit 5a61798

File tree

6 files changed

+71
-59
lines changed

6 files changed

+71
-59
lines changed

bdshemu/bdshemu.c

+64-57
Original file line numberDiff line numberDiff line change
@@ -1187,82 +1187,89 @@ ShemuGetOperandValue(
11871187
else if (op->Type == ND_OP_MEM)
11881188
{
11891189
uint64_t gla = ShemuComputeLinearAddress(Context, op);
1190+
uint32_t offset;
1191+
uint8_t seg;
11901192

11911193
if (op->Info.Memory.IsAG)
11921194
{
11931195
// Address generation instruction, the result is the linear address itself.
11941196
Value->Value.Qwords[0] = gla;
1197+
goto done_gla;
1198+
}
1199+
1200+
if (Context->Ring == 3)
1201+
{
1202+
// User-mode TIB offset that contains the PEB address.
1203+
offset = Context->Mode == ND_CODE_32 ? 0x30 : 0x60;
1204+
seg = Context->Mode == ND_CODE_32 ? ND_PREFIX_G2_SEG_FS : ND_PREFIX_G2_SEG_GS;
11951205
}
11961206
else
11971207
{
1198-
uint32_t offset;
1199-
uint8_t seg;
1208+
// Kernel-mode KPCR offset that contains the current KTHREAD address.
1209+
offset = Context->Mode == ND_CODE_32 ? 0x124 : 0x188;
1210+
seg = Context->Mode == ND_CODE_32 ? ND_PREFIX_G2_SEG_FS : ND_PREFIX_G2_SEG_GS;
1211+
}
12001212

1201-
if (Context->Ring == 3)
1202-
{
1203-
// User-mode TIB offset that contains the PEB address.
1204-
offset = Context->Mode == ND_CODE_32 ? 0x30 : 0x60;
1205-
seg = Context->Mode == ND_CODE_32 ? ND_PREFIX_G2_SEG_FS : ND_PREFIX_G2_SEG_GS;
1206-
}
1207-
else
1208-
{
1209-
// Kernel-mode KPCR offset that contains the current KTHREAD address.
1210-
offset = Context->Mode == ND_CODE_32 ? 0x124 : 0x188;
1211-
seg = Context->Mode == ND_CODE_32 ? ND_PREFIX_G2_SEG_FS : ND_PREFIX_G2_SEG_GS;
1212-
}
1213+
// Check if this is a TIB/PCR access. Make sure the FS/GS register is used for the access, in order to avoid
1214+
// false positives where legitimate code accesses a linear TIB directly.
1215+
// Note that this covers accesses to the PEB field inside the TIB.
1216+
if (gla == Context->TibBase + offset && Context->Instruction.Seg == seg)
1217+
{
1218+
Context->Flags |= SHEMU_FLAG_TIB_ACCESS;
1219+
}
12131220

1214-
// Check if this is a TIB/PCR access. Make sure the FS/GS register is used for the access, in order to avoid
1215-
// false positives where legitimate code accesses a linear TIB directly.
1216-
// Note that this covers accesses to the PEB field inside the TIB.
1217-
if (gla == Context->TibBase + offset && Context->Instruction.Seg == seg)
1218-
{
1219-
Context->Flags |= SHEMU_FLAG_TIB_ACCESS;
1220-
}
1221+
// Note that this covers accesses to the Wow32Reserved in Wow64 mode. That field can be used to issue
1222+
// syscalls.
1223+
if (gla == Context->TibBase + 0xC0 && Context->Instruction.Seg == seg && Context->Mode == ND_CODE_32)
1224+
{
1225+
Context->Flags |= SHEMU_FLAG_TIB_ACCESS_WOW32;
1226+
}
12211227

1222-
// Note that this covers accesses to the Wow32Reserved in Wow64 mode. That field can be used to issue
1223-
// syscalls.
1224-
if (gla == Context->TibBase + 0xC0 && Context->Instruction.Seg == seg && Context->Mode == ND_CODE_32)
1225-
{
1226-
Context->Flags |= SHEMU_FLAG_TIB_ACCESS_WOW32;
1227-
}
1228+
// Check for accesses inside the KUSER_SHARED_DATA (SharedUserData). This page contains some
1229+
// global system information, it may host shellcodes, and is hard-coded at this address.
1230+
if (gla >= 0x7FFE0000 && gla < 0x7FFE1000)
1231+
{
1232+
Context->Flags |= SHEMU_FLAG_SUD_ACCESS;
1233+
}
12281234

1229-
// Check if we are reading a previously saved RIP. Ignore RET category, which naturally uses the saved RIP.
1230-
// Also, ignore RMW instruction which naturally read the current value - this could happen if the code
1231-
// modifies the return value, for example "ADD qword [rsp], r8".
1232-
if (Context->Instruction.Category != ND_CAT_RET && !(op->Access.Access & ND_ACCESS_ANY_WRITE) &&
1233-
ShemuIsStackPtr(Context, gla, op->Size) &&
1234-
ShemuAnyBitsSet(STACKBMP(Context), gla - Context->StackBase, op->Size))
1235-
{
1236-
Context->Flags |= SHEMU_FLAG_LOAD_RIP;
1237-
}
1235+
// Check if we are reading a previously saved RIP. Ignore RET category, which naturally uses the saved RIP.
1236+
// Also, ignore RMW instruction which naturally read the current value - this could happen if the code
1237+
// modifies the return value, for example "ADD qword [rsp], r8".
1238+
if (Context->Instruction.Category != ND_CAT_RET && !(op->Access.Access & ND_ACCESS_ANY_WRITE) &&
1239+
ShemuIsStackPtr(Context, gla, op->Size) &&
1240+
ShemuAnyBitsSet(STACKBMP(Context), gla - Context->StackBase, op->Size))
1241+
{
1242+
Context->Flags |= SHEMU_FLAG_LOAD_RIP;
1243+
}
12381244

1239-
// Get the memory value.
1240-
status = ShemuGetMemValue(Context, gla, Value->Size, Value->Value.Bytes);
1241-
if (SHEMU_SUCCESS != status)
1242-
{
1243-
return status;
1244-
}
1245+
// Get the memory value.
1246+
status = ShemuGetMemValue(Context, gla, Value->Size, Value->Value.Bytes);
1247+
if (SHEMU_SUCCESS != status)
1248+
{
1249+
return status;
1250+
}
12451251

1246-
// If this is a stack access, we need to update the stack pointer.
1247-
if (op->Info.Memory.IsStack)
1248-
{
1249-
uint64_t regval = ShemuGetGprValue(Context, NDR_RSP, (2 << Context->Instruction.DefStack), false);
1252+
// If this is a stack access, we need to update the stack pointer.
1253+
if (op->Info.Memory.IsStack)
1254+
{
1255+
uint64_t regval = ShemuGetGprValue(Context, NDR_RSP, (2 << Context->Instruction.DefStack), false);
12501256

1251-
regval += op->Size;
1257+
regval += op->Size;
12521258

1253-
ShemuSetGprValue(Context, NDR_RSP, (2 << Context->Instruction.DefStack), regval, false);
1254-
}
1259+
ShemuSetGprValue(Context, NDR_RSP, (2 << Context->Instruction.DefStack), regval, false);
1260+
}
12551261

1256-
// If this is a string operation, make sure we update RSI/RDI.
1257-
if (op->Info.Memory.IsString)
1258-
{
1259-
uint64_t regval = ShemuGetGprValue(Context, op->Info.Memory.Base, op->Info.Memory.BaseSize, false);
1262+
// If this is a string operation, make sure we update RSI/RDI.
1263+
if (op->Info.Memory.IsString)
1264+
{
1265+
uint64_t regval = ShemuGetGprValue(Context, op->Info.Memory.Base, op->Info.Memory.BaseSize, false);
12601266

1261-
regval = GET_FLAG(Context, NDR_RFLAG_DF) ? regval - op->Size : regval + op->Size;
1267+
regval = GET_FLAG(Context, NDR_RFLAG_DF) ? regval - op->Size : regval + op->Size;
12621268

1263-
ShemuSetGprValue(Context, op->Info.Memory.Base, op->Info.Memory.BaseSize, regval, false);
1264-
}
1269+
ShemuSetGprValue(Context, op->Info.Memory.Base, op->Info.Memory.BaseSize, regval, false);
12651270
}
1271+
1272+
done_gla:;
12661273
}
12671274
else if (op->Type == ND_OP_IMM)
12681275
{
@@ -2414,7 +2421,7 @@ ShemuEmulate(
24142421
}
24152422

24162423
// We may, in the future, emulate far branches, but they imply some tricky context switches (including
2417-
// the default TEB), so it may not be as straight forward as it seems. For now, al we wish to achieve
2424+
// the default TEB), so it may not be as straight forward as it seems. For now, all we wish to achieve
24182425
// is detection of far branches in long-mode, from Wow 64.
24192426
stop = true;
24202427
break;

bdshemu_test/bdshemu_test.zip

710 Bytes
Binary file not shown.

disasmtool/disasmtool.c

+4
Original file line numberDiff line numberDiff line change
@@ -1673,6 +1673,10 @@ handle_shemu(
16731673
{
16741674
printf(" SHEMU_FLAG_STACK_PIVOT\n");
16751675
}
1676+
if (ctx.Flags & SHEMU_FLAG_SUD_ACCESS)
1677+
{
1678+
printf(" SHEMU_FLAG_SUD_ACCESS\n");
1679+
}
16761680
if (ctx.Flags & SHEMU_FLAG_KPCR_ACCESS)
16771681
{
16781682
printf(" SHEMU_FLAG_KPCR_ACCESS\n");

inc/bdshemu.h

+1
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,7 @@ typedef unsigned int SHEMU_STATUS;
254254
#define SHEMU_FLAG_TIB_ACCESS_WOW32 0x00000040 // The code accesses the Wow32Reserved field inside TIB.
255255
#define SHEMU_FLAG_HEAVENS_GATE 0x00000080 // The code uses Heaven's gate to switch into 64 bit mode.
256256
#define SHEMU_FLAG_STACK_PIVOT 0x00000100 // The code switched the stack using XCHG esp, *.
257+
#define SHEMU_FLAG_SUD_ACCESS 0x00000200 // The code accesses the KUSER_SHARED_DATA page.
257258
// Kernel specific flags.
258259
#define SHEMU_FLAG_KPCR_ACCESS 0x00010000 // KPCR current thread access via gs:[0x188]/fs:[0x124].
259260
#define SHEMU_FLAG_SWAPGS 0x00020000 // SWAPGS was executed.

inc/version.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,6 @@
77

88
#define DISASM_VERSION_MAJOR 1
99
#define DISASM_VERSION_MINOR 34
10-
#define DISASM_VERSION_REVISION 1
10+
#define DISASM_VERSION_REVISION 2
1111

1212
#endif // DISASM_VER_H

pybddisasm/setup.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
from codecs import open
1313

1414
VERSION = (0, 1, 3)
15-
LIBRARY_VERSION = (1, 34, 1)
15+
LIBRARY_VERSION = (1, 34, 2)
1616
LIBRARY_INSTRUX_SIZE = 864
1717

1818
packages = ['pybddisasm']

0 commit comments

Comments
 (0)