获取封装在命名空间

时间:2018-01-06 21:19:36

标签: c++ assembly

我有两个类似的文件:

a.cpp

#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);
}

b.cpp

int hack()
{
    return 31;
}

我无法编辑a.cpp。 我想编写这样的hack()函数,以便能够从b.cpp获取mysecret值(我认为应该通过获取其地址来完成)。有没有办法做到这一点?

我试图反汇编文件。好像mysecret存储在0x0(%% rip)中,所以如果我们可以获得%% rip寄存器状态,当mysecret被cin&#39; ed时,我们就可以获得它。

2 个答案:

答案 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);