Я хотел бы написать небольшой преобразователь, который будет вызывать базовую функцию, а затем сравнивать значение rsp
до и после вызова. Важно отметить, что этот код не должен стирать регистры.
Очевидная реализация состоит в том, чтобы просто выполнить push rsp
перед вызовом, а затем сравнить его после. Проблема в том, что push rsp
сама вычитает 8 из стека, так что вам действительно нужно сравнить сохраненное значение rsp
со значением после вызова плюс 8.
Вот один из способов сделать это:
foo_thunk:
push rsp ; save the value of rsp
call foo ; call the underlying function
add rsp, 8 ; adjust rsp by 8, popping the saved value
cmp rsp, [rsp - 8]
jne bad_rsp ; bad foo!
ret
Проблема в том, что при этом осуществляется доступ к значению [rsp - 8]
, которое выше rsp
, то есть не в стеке, а в туманной области над стеком. Это должно быть там, где у вас есть красная зона, но не тогда, когда ее нет.
Какие есть альтернативы? Производительность и размер кода важны.
rsp
перед сравнением, поэтому вам не нужно обращаться к указателю стека. Хуже того, в стеке могут быть аргументы, которые вам нужно обработать. - person Jester   schedule 25.10.2017rsp
будет уничтожен, скорее всего,foo
не вернется к вам, поэтому я не вижу особого смысла проверять. XY проблема? - person Jester   schedule 25.10.2017sub rsp,8
push verify_rsp_is_valid
call foo_with_no_args_in_stack
ret
verify_rsp_is_valid: add rsp,8
ret
. Будет продолжаться правильно только тогда, когдаrsp
будет действительным, илиfoo
поймет вашу хитрость и прыгнет напрямую или оставитverify_rsp_is_valid
адрес в стеке на нужном месте. В случае плохогоrsp
вы случайно окажетесь в другом месте. Но это то же самое, что и обычныйfoo
в любом случае, поэтому практическое удобство использования выглядит близким к нулю, я бы скорее понял, что какая-то канареечная система проверяет перезапись стека, чем проверяет самrsp
. - person Ped7g   schedule 25.10.2017rsp
(но это не сработает). Канарейка проверяет перезапись (и, как и эта проверка, лучше всего подходит дляcallee
, так как она не будет работать в преобразователе). - person BeeOnRope   schedule 25.10.2017foo_with_no_args_in_stack
... но в целом это просто очень глупая альтернатива, если подумать. Кроме того, даже если это прозрачно для обычного кода, это приветствуется как вектор атаки для любого вредоносного кода, поэтому я бы определенно не советовал использовать что-то подобное. Насколько я понимаю, еслиcall foo
позже дойдет до следующей инструкции, это означает, чтоrsp
верна на 99,99%, или вы подверглись сильной атаке. Другой альтернативой может быть самостоятельная модификация для сохраненияrsp
как непосредственного дляcmp
, ноcmp rsp,imm64
недействительна?? - person Ped7g   schedule 25.10.2017cmp esp,imm32
может быть достаточно! - person Ped7g   schedule 25.10.2017rsp
в преобразователе кажется DOA. - person BeeOnRope   schedule 25.10.2017call
подталкивает адрес возврата. Таким образом,sub rsp, 8
снова выравнивает его. - person BeeOnRope   schedule 25.10.2017