通过自修改代码进行动态混淆

时间:2010-12-27 20:02:13

标签: c assembly obfuscation

这就是我想要做的事情:

假设你有两个功能

void f1(int *v)
{
   *v = 55;
}
void f2(int *v)
{
   *v = 44;
}

char *template;
template = allocExecutablePages(...);

char *allocExecutablePages (int pages)
{
    template = (char *) valloc (getpagesize () * pages);
    if (mprotect (template, getpagesize (),
        PROT_READ|PROT_EXEC|PROT_WRITE) == -1) {
            perror (“mprotect”);
    }
}

我想在f1和f2之间做一个比较(所以说明什么是相同的,什么不是)(所以得到那些函数的装配线并逐行比较) 然后将这些行放在我的模板中。

C中有没有办法做到这一点?

感谢

更新

感谢所有你回答的人,但也许我没有正确解释我的需要。

基本上我正在尝试编写一个小混淆方法。 这个想法包括让两个或多个函数在内存中共享相同的位置。内存区域(我们将称之为模板)设置为包含一些内存区域 来自函数的机器代码字节,更具体地说,它们都是函数 有共同点。在执行特定功能之前,使用编辑脚本 用必要的机器代码字节修补模板以创建一个 该功能的完整版本。当另一个功能分配给同一个 模板即将被执行,这个过程重复,这次是用 不同的编辑脚本。为了说明这一点,假设你想混淆一个 程序包含两个函数f1和f2。第一个(f1)有 跟随机器代码字节

Address Machine code
0          10
1          5
2          6
3          20
and the second one (f2) has
Address Machine code
0          10
1          9
2          3
3          20
At obfuscation time, one will replace f1 and f2 by the template
Address Machine code
0           10
1           ?
2           ? 
3           20
and by the two edit scripts e1 = {1 becomes 5, 2 becomes 6} and e2 = {1
becomes 9, 2 becomes 3}.


#include <stdlib.h>
#include <string.h>

typedef unsigned int uint32;
typedef char * addr_t;

typedef struct {
uint32 offset;
char value;
} EDIT;

EDIT script1[200], script2[200];
char *template;
int template_len, script_len = 0;
typedef void(*FUN)(int *);
int val, state = 0;

void f1_stub ()
{
if (state != 1) {
patch (script1, script_len, template);
state = 1;
}
((FUN)template)(&val);
}

void f2_stub () {
if (state != 2) {
patch (script2, script_len, template);
state = 2;
}
((FUN)template)(&val);
}

int new_main (int argc, char **argv)
{
f1_stub ();
f2_stub ();
return 0;
}

void f1 (int *v) { *v = 99; }
void f2 (int *v) { *v = 42; }

int main (int argc, char **argv)
{
int f1SIZE, f2SIZE;
/* makeCodeWritable (...); */
/* template = allocExecutablePages(...); */
/* Computed at obfuscation time */
diff ((addr_t)f1, f1SIZE,
(addr_t)f2, f2SIZE,
script1, script2,
&script_len,
template,
&template_len);
/* We hide the proper code */
memset (f1, 0, f1SIZE);
memset (f2, 0, f2SIZE);
return new_main (argc, argv);
}

所以我现在需要编写diff函数。这将获取我的两个函数的地址,并将生成一个带有相关脚本的模板。

这就是为什么我想比较字节我的两个函数

对不起,我的第一篇文章不是很容易理解!

谢谢

4 个答案:

答案 0 :(得分:2)

您想在运行时或作者身份期间执行此操作吗?

您可以指示您的C编译器生成汇编语言输出,例如gcc具有-S选项,它将在file.s中生成输出。您的编译器套件也可能有一个类似objdump的程序,它可以反编译目标文件或整个可执行文件。但是,您通常希望将优化保留为现代编译器而不是自己编写。

在运行时&amp; operator可以获取函数的地址,你可以通读它,虽然你必须为在任何有趣的事情之前遇到分支指令的可能性做好准备,所以你实际上必须以编程方式“理解”指令集的至少一个子集。阅读函数指针时遇到的问题当然会因机器,ABI,编译器,优化标志等而异。

答案 1 :(得分:1)

将函数放入t1.ct2.c使用gcc -S生成汇编输出:

gcc -S t1.c
gcc -S t2.c

现在比较t1.st2.s

答案 2 :(得分:1)

如果您使用的是Visual Studio,请转到

Project Properties -> Configuration -> C/C++ -> Output Files -> Assembler output

或使用编译器开关/FA/FAc/FAs/FAcs。小写c表示输出机器代码s - 源代码与汇编代码并排。并且不要忘记禁用编译器优化。

答案 3 :(得分:0)

阅读了一些答案和那里的评论,我不确定我是否完全理解你的问题,但也许你正在寻找一个gcc调用,如下所示:
gcc -S -xc - -o -

这告诉gcc从stdin输出C代码并输出汇编到stdout。

如果使用类似vi的编辑器,可以在可视模式下突出显示功能体,然后运行命令:
:'<,'>!gcc -S -xc - -o - 2> /dev/null
...这将用汇编代替函数体(“stderr&gt; / dev / null”业务是跳过关于#include的错误。)

否则,您可以将此gcc调用用作脚本中管道的一部分。