1
1
/*
2
2
* Copyright (C) 2008-2022 Ole André Vadla Ravnås <[email protected] >
3
3
* Copyright (C) 2008 Christian Berentsen <[email protected] >
4
+ * Copyright (C) 2024 Yannis Juglaret <[email protected] >
4
5
*
5
6
* Licence: wxWindows Library Licence, Version 3.1
6
7
*/
@@ -46,6 +47,7 @@ struct _GumInterceptorBackend
46
47
struct _GumX86FunctionContextData
47
48
{
48
49
guint redirect_code_size ;
50
+ gpointer push_to_shadow_stack ;
49
51
};
50
52
51
53
G_STATIC_ASSERT (sizeof (GumX86FunctionContextData )
@@ -61,7 +63,7 @@ static void gum_emit_leave_thunk (GumX86Writer * cw);
61
63
62
64
static void gum_emit_prolog (GumX86Writer * cw ,
63
65
gssize stack_displacement );
64
- static void gum_emit_epilog (GumX86Writer * cw );
66
+ static void gum_emit_epilog (GumX86Writer * cw , GumPointCut point_cut );
65
67
66
68
GumInterceptorBackend *
67
69
_gum_interceptor_backend_create (GRecMutex * mutex ,
@@ -171,6 +173,7 @@ _gum_interceptor_backend_create_trampoline (GumInterceptorBackend * self,
171
173
GumX86Relocator * rl = & self -> relocator ;
172
174
GumX86FunctionContextData * data = GUM_FCDATA (ctx );
173
175
GumAddress function_ctx_ptr ;
176
+ gpointer after_push_to_shadow_stack ;
174
177
guint reloc_bytes ;
175
178
176
179
if (!gum_interceptor_backend_prepare_trampoline (self , ctx ))
@@ -189,6 +192,27 @@ _gum_interceptor_backend_create_trampoline (GumInterceptorBackend * self,
189
192
gum_x86_writer_put_push_near_ptr (cw , function_ctx_ptr );
190
193
gum_x86_writer_put_jmp_address (cw , GUM_ADDRESS (self -> enter_thunk -> data ));
191
194
195
+ if ((cw -> cpu_features & GUM_CPU_CET_SS ) != 0 )
196
+ {
197
+ /*
198
+ * Jumping to push_to_shadow_stack will push the on_leave_trampoline
199
+ * address onto the shadow stack, thereby making it a legit address to
200
+ * return to. Then it will jump back through XAX.
201
+ */
202
+
203
+ after_push_to_shadow_stack = gum_x86_writer_cur (cw );
204
+
205
+ gum_x86_writer_put_lea_reg_reg_offset (cw , GUM_X86_XSP ,
206
+ GUM_X86_XSP , (gssize ) sizeof (gpointer ));
207
+
208
+ gum_x86_writer_put_jmp_reg (cw , GUM_X86_XAX );
209
+
210
+ data -> push_to_shadow_stack = gum_x86_writer_cur (cw );
211
+
212
+ gum_x86_writer_put_call_address (cw ,
213
+ GUM_ADDRESS (after_push_to_shadow_stack ));
214
+ }
215
+
192
216
ctx -> on_leave_trampoline = gum_x86_writer_cur (cw );
193
217
194
218
gum_x86_writer_put_push_near_ptr (cw , function_ctx_ptr );
@@ -321,6 +345,8 @@ static void
321
345
gum_emit_enter_thunk (GumX86Writer * cw )
322
346
{
323
347
const gssize return_address_stack_displacement = 0 ;
348
+ const gchar * prepare_trap_on_leave = "prepare_trap_on_leave" ;
349
+ gpointer epilog ;
324
350
325
351
gum_emit_prolog (cw , return_address_stack_displacement );
326
352
@@ -338,7 +364,26 @@ gum_emit_enter_thunk (GumX86Writer * cw)
338
364
GUM_ARG_REGISTER , GUM_X86_XDX ,
339
365
GUM_ARG_REGISTER , GUM_X86_XCX );
340
366
341
- gum_emit_epilog (cw );
367
+ if ((cw -> cpu_features & GUM_CPU_CET_SS ) != 0 )
368
+ {
369
+ gum_x86_writer_put_test_reg_reg (cw , GUM_X86_EAX , GUM_X86_EAX );
370
+ gum_x86_writer_put_jcc_short_label (cw , X86_INS_JNE , prepare_trap_on_leave ,
371
+ GUM_NO_HINT );
372
+
373
+ epilog = gum_x86_writer_cur (cw );
374
+ }
375
+
376
+ gum_emit_epilog (cw , FALSE);
377
+
378
+ if ((cw -> cpu_features & GUM_CPU_CET_SS ) != 0 )
379
+ {
380
+ gum_x86_writer_put_label (cw , prepare_trap_on_leave );
381
+
382
+ gum_x86_writer_put_mov_reg_address (cw , GUM_X86_XAX , GUM_ADDRESS (epilog ));
383
+ gum_x86_writer_put_jmp_reg_offset_ptr (cw , GUM_X86_XBX ,
384
+ G_STRUCT_OFFSET (GumFunctionContext , backend_data ) +
385
+ G_STRUCT_OFFSET (GumX86FunctionContextData , push_to_shadow_stack ));
386
+ }
342
387
}
343
388
344
389
static void
@@ -359,7 +404,7 @@ gum_emit_leave_thunk (GumX86Writer * cw)
359
404
GUM_ARG_REGISTER , GUM_X86_XSI ,
360
405
GUM_ARG_REGISTER , GUM_X86_XDX );
361
406
362
- gum_emit_epilog (cw );
407
+ gum_emit_epilog (cw , TRUE );
363
408
}
364
409
365
410
static void
@@ -401,7 +446,8 @@ gum_emit_prolog (GumX86Writer * cw,
401
446
}
402
447
403
448
static void
404
- gum_emit_epilog (GumX86Writer * cw )
449
+ gum_emit_epilog (GumX86Writer * cw ,
450
+ GumPointCut point_cut )
405
451
{
406
452
guint8 fxrstor [] = {
407
453
0x0f , 0xae , 0x0c , 0x24 /* fxrstor [esp] */
@@ -415,5 +461,17 @@ gum_emit_epilog (GumX86Writer * cw)
415
461
GumCpuContext.xip */
416
462
gum_x86_writer_put_popax (cw );
417
463
gum_x86_writer_put_popfx (cw );
418
- gum_x86_writer_put_ret (cw );
464
+
465
+ if (point_cut == GUM_POINT_LEAVE )
466
+ {
467
+ gum_x86_writer_put_ret (cw );
468
+ }
469
+ else
470
+ {
471
+ /* Emulate a ret without affecting the shadow stack. */
472
+ gum_x86_writer_put_lea_reg_reg_offset (cw , GUM_X86_XSP ,
473
+ GUM_X86_XSP , sizeof (gpointer ));
474
+ gum_x86_writer_put_jmp_reg_offset_ptr (cw , GUM_X86_XSP ,
475
+ - ((gssize ) sizeof (gpointer )));
476
+ }
419
477
}
0 commit comments