【问题标题】:Can we scramble the declaration order in C or C++?我们可以打乱 C 或 C++ 中的声明顺序吗?
【发布时间】:2015-01-27 11:19:32
【问题描述】:

是否有方法/插件/插件可以忽略以下子句(对于某些 c/c++ 编译器)?在与预处理器或类似阶段相同的阶段重新排序结构中的成员声明?或许可以在结构声明的前面添加一个关键字,比如 volatile 或类似的东西。

我在想:编译器选项、内置关键字或编程方法。

C99 §6.7.2.1 clause 13 states:

在结构对象中, 非位域成员和单元 哪些位域驻留有地址 增加的顺序 它们被声明了。

C++ 似乎也有类似的子句,我对此也很感兴趣。这两个子句都指定了一个合理的特征,即在以后的声明中具有更大的内存偏移量。但是,出于接口目的或其他目的,我通常不需要知道我的结构的声明顺序。写一些代码就好了:

scrambled struct foo {
    int a;
    int bar;
};

或者,假设这个结构的顺序并不重要。

scrambled struct foo {
    int bar;
    int a;
};

因此,每次编译时都会随机交换ab 的声明。我相信这也适用于留出堆栈内存。

main() {
    scrambled int a;
    scrambled int foo;
    scrambled int bar;
    ..

我为什么要问?

我很好奇程序机器人是如何创建的。我看到一些人在运行将要创建 hack 的程序时分析内存偏移量的变化。

似乎过程是:观察内存偏移量并记下给定偏移量的用途。稍后,hack 程序会在这些偏移处将所需的值注入内存。

现在假设每次编译程序时这些内存偏移都会改变。也许它会阻碍或劝阻人们花时间去理解你希望他们不知道的事情。

【问题讨论】:

  • 为什么不自己重新排序结构等?而某人在他/她自己的计算机上做什么,而不影响其他任何事情,这与您无关。别理他们。如果它可能伤害(等)其他人,无论如何你都需要额外的安全措施,比变量重新排序更好。
  • 可以想象一个扩展,但出于性能原因:它允许成员对齐,成员之间的填充最小。我所知道的任何编译器都没有这样的扩展。
  • @deviantfan 他们可以这样做,只有当他们期望该行为在他们下载的版本之间持续存在时才会影响他们。
  • @ouah 填充可以持续存在,因为我正在考虑在类似预处理器的阶段会重新排序的东西。
  • @Leonardo 如果他们破坏了他们的程序设置或其他什么,这是他们自己的错。我不会太担心这一点。 (如果有人通过更改内存位置来做事,他/她也应该找到剩余的注册表项等)

标签: c++ c memory struct c99


【解决方案1】:

您的意图是好的,但解决方案不是(对不起)。通常你不能在每次运行之前重新编译你的程序。攻击者将破解被检查的程序。但是,有一个解决方案,称为ASLR。操作系统可以为您更改加载地址,从而使“面向返回的编程”和“像黑客一样返回 libc 更加困难”。

【讨论】:

  • 如果我们谈论的客户端必须始终连接到服务器并在使用前进行自我更新,那不是要求攻击者始终动态地提出解决方案吗?
  • 如果攻击者在本地运行程序,在他自己的机器上,你已经丢失了那个实例。在不受信任的计算机上没有任何内容是受信任的。例如:电脑游戏。没有破解/破解。
  • 我明白了,所以你的意思是永远不要依赖缺乏独创性。从我所看到的情况来看,似乎破解一些简单的东西严重依赖于寻找内存偏移量,而让它们改变可能会导致悲伤。我真的对一种务实的劝阻方法感兴趣,而不是建立一个密封的安全系统。
【解决方案2】:

运行时foxing 是最好的方法,那么你只需要发布一个版本。如果struct 有多个相同类型的字段,则可以使用数组代替。步骤 1. 使用数组代替具有三个 int 字段的结构

#define foo 0
#define bar 1
#define zee 2

struct abc {
    int scramble [3];
};

...
value = abc.scramble[bar];

第 2 步,现在使用每次运行程序时随机排列的索引数组。

int abcindex [3];               // index lookup 
int abcpool  [3];               // index pool for randomise

for (i=0; i<3; i++)             // initialise index pool
    abcpool[i] = i;

srand (time(NULL));
for (i=0; i<3; i++) {           // initialise lookup array
    j = rand()%(3-i);
    abcindex[i] = abcpool[j];   // allocate random index from pool
    abcpool[j] = abcpool[2-i];  // remove index from pool
    }

value = abc.scramble[abcindex[bar]];

另一种试图欺骗黑客的方法是包含伪装变量,这些变量的行为好像与黑客有关,但如果被篡改则使程序退出。最后,您可以保留某种校验和或密钥变量的加密副本,以检查它们是否被篡改。

【讨论】:

  • 谢谢,这是很好的输入。我想知道是否有任何不错的库可以以这种方式使用数组进行封装。我希望最大限度地减少程序员实施这些做法所需的工作量,同时让恶意用户难以规避。
  • 防篡改方法会推迟一些但不是全部。熟练的恶意用户会反汇编您的程序并修补检查。
猜你喜欢
  • 1970-01-01
  • 2016-02-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-20
  • 2021-10-12
  • 2022-01-22
  • 1970-01-01
相关资源
最近更新 更多