@@ -1187,82 +1187,89 @@ ShemuGetOperandValue(
1187
1187
else if (op -> Type == ND_OP_MEM )
1188
1188
{
1189
1189
uint64_t gla = ShemuComputeLinearAddress (Context , op );
1190
+ uint32_t offset ;
1191
+ uint8_t seg ;
1190
1192
1191
1193
if (op -> Info .Memory .IsAG )
1192
1194
{
1193
1195
// Address generation instruction, the result is the linear address itself.
1194
1196
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 ;
1195
1205
}
1196
1206
else
1197
1207
{
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
+ }
1200
1212
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
+ }
1213
1220
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
+ }
1221
1227
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
+ }
1228
1234
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
+ }
1238
1244
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
+ }
1245
1251
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);
1250
1256
1251
- regval += op -> Size ;
1257
+ regval += op -> Size ;
1252
1258
1253
- ShemuSetGprValue (Context , NDR_RSP , (2 << Context -> Instruction .DefStack ), regval , false);
1254
- }
1259
+ ShemuSetGprValue (Context , NDR_RSP , (2 << Context -> Instruction .DefStack ), regval , false);
1260
+ }
1255
1261
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);
1260
1266
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 ;
1262
1268
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);
1265
1270
}
1271
+
1272
+ done_gla :;
1266
1273
}
1267
1274
else if (op -> Type == ND_OP_IMM )
1268
1275
{
@@ -2414,7 +2421,7 @@ ShemuEmulate(
2414
2421
}
2415
2422
2416
2423
// 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
2418
2425
// is detection of far branches in long-mode, from Wow 64.
2419
2426
stop = true;
2420
2427
break ;
0 commit comments