我有两个类似的文件:
#include <iostream>
#include <cassert>
using namespace std;
int hack();
typedef int (*hackFunction)();
namespace secret
{
static int mysecret;
int _main(hackFunction hack)
{
cin >> mysecret;
assert(hack() == mysecret);
return 0;
}
}
int main()
{
return secret::_main(hack);
}
int hack()
{
return 31;
}
我无法编辑a.cpp。 我想编写这样的hack()函数,以便能够从b.cpp获取mysecret值(我认为应该通过获取其地址来完成)。有没有办法做到这一点?
我试图反汇编文件。好像mysecret存储在0x0(%% rip)中,所以如果我们可以获得%% rip寄存器状态,当mysecret被cin&#39; ed时,我们就可以获得它。
答案 0 :(得分:1)
它是特定于编译的。 你没有提供反汇编,所以我使用gcc 7.2作为例子 (https://godbolt.org/g/oUAvcG),第10-15行:
mov esi, OFFSET FLAT:secret::mysecret ; move mysecret (value of address) to ESI
mov edi, OFFSET FLAT:std::cin ; pass handle to stdout
call std::basic_istream<char, std::char_traits<char> >::operator>>(int&) ; print mysecret
mov rax, QWORD PTR [rbp-8] ; move hack() address to RAX
call rax ; calls to hack() by register
我们无法从我们可以编写的代码(b.cpp
)知道它的偏移量
RIP
寄存器仅显示下一次处理器的位置,但不显示mysecret
地址。
如果您现在调用hack()
约定,则只能确定返回地址。如果mysecret
是常量,则返回地址的偏移量将是您的答案,但您只有地址并且必须返回它的值。
如果hack()
为cdecl
,则返回地址将在ESP
开始时为hack()
计算10行和16行地址之间的字节差异,并得到它的值。所以,hack()将是这样的:
int __naked hack()
{
__asm
{
mov ecx, esp ; return value in main() after hack() is called
sub ecx, <value> ; <value> is the constant offset to mysecret address
mov eax, [ecx] ; read mysecret address hardcoded in assembly
mov eax, [eax] ; return mysecret value
ret ; extiting subroutine
}
}
另外,
答案 1 :(得分:0)
一种方法是让你的函数获取类似的变量(如果它有权访问它):
results[0]
另一种方式就像你说的那样将指向变量的指针传递给函数,如下所示:
int hack()
{
return secret::mysecret;
}
当你这样称呼它时传递它:
int hack(int *secret)
{
return *secret;
}
你必须改变这样的签名:
assert(hack(&mysecret) == mysecret);