自修改代码 [C++]
我正在阅读一篇有关自修改代码的密码破译者期刊文章,其中有这样的代码片段:
void Demo(int (*_printf) (const char *,...))
{
_printf("Hello, OSIX!n");
return;
}
int main(int argc, char* argv[])
{
char buff[1000];
int (*_printf) (const char *,...);
int (*_main) (int, char **);
void (*_Demo) (int (*) (const char *,...));
_printf=printf;
int func_len = (unsigned int) _main - (unsigned int) _Demo;
for (int a=0; a<func_len; a++)
buff[a] = ((char *) _Demo)[a];
_Demo = (void (*) (int (*) (const char *,...))) &buff[0];
_Demo(_printf);
return 0;
}
此代码据说在堆栈上执行了 Demo()。我理解大部分代码,但他们分配“func_len”的部分让我感到困惑。据我所知,他们正在从另一个随机指针地址中减去一个随机指针地址。
有人愿意解释一下吗?
I was reading a codebreakers journal article on self-modifying code and there was this code snippet:
void Demo(int (*_printf) (const char *,...))
{
_printf("Hello, OSIX!n");
return;
}
int main(int argc, char* argv[])
{
char buff[1000];
int (*_printf) (const char *,...);
int (*_main) (int, char **);
void (*_Demo) (int (*) (const char *,...));
_printf=printf;
int func_len = (unsigned int) _main - (unsigned int) _Demo;
for (int a=0; a<func_len; a++)
buff[a] = ((char *) _Demo)[a];
_Demo = (void (*) (int (*) (const char *,...))) &buff[0];
_Demo(_printf);
return 0;
}
This code supposedly executed Demo() on the stack. I understand most of the code, but the part where they assign 'func_len' confuses me. As far as i can tell, they're subtracting one random pointer address from another random pointer address.
Someone care to explain?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
该代码依赖于编译器对函数布局的了解 - 这对于其他编译器可能不可靠。
func_len
行经过更正以包含最初缺失的-
后,通过减去中的地址来确定函数
(应该包含Demo
的长度>_DemoDemo()
的起始地址)来自_main
中的地址(应该包含main()
)。假定这是函数Demo
的长度,然后将其按字节复制到缓冲区buff
中。然后,buff
的地址被强制转换为函数指针,然后调用该函数。但是,由于_Demo
和_main
都没有实际初始化,因此代码存在极大的错误。此外,尚不清楚unsigned int
是否足够大以准确保存指针;转换可能应该是来自
或
的uintptr_t
。如果错误已修复,如果有关代码布局的假设正确,如果代码是与位置无关的代码,并且没有针对执行数据空间的保护,则此方法有效。它不可靠、不可移植且不推荐。但它确实说明,如果有效的话,代码和数据非常相似。
我记得在两个进程之间进行了类似的特技,将一个函数从一个程序复制到共享内存中,然后让另一个程序从共享内存中执行该函数。那是大约四分之一世纪前的事了,但这项技术是相似的,并且对于它所尝试的机器来说“有效”。从那以后我再也不需要使用这项技术了,谢天谢地!
The code is relying on knowledge of the layout of functions from the compiler - which may not be reliable with other compilers.
The
func_len
line, once corrected to include the-
that was originally missing, determines the length of the functionDemo
by subtracting the address in_Demo
(which is is supposed to contain the start address ofDemo()
) from the address in_main
(which is supposed to contain the start address ofmain()
). This is presumed to be the length of the functionDemo
, which is then copied byte-wise into the bufferbuff
. The address ofbuff
is then coerced into a function pointer and the function then called. However, since neither_Demo
nor_main
is actually initialized, the code is buggy in the extreme. Also, it is not clear that anunsigned int
is big enough to hold pointers accurately; the cast should probably be to auintptr_t
from<stdint.h>
or<inttypes.h>
.This works if the bugs are fixed, if the assumptions about the code layout are correct, if the code is position-independent code, and if there are no protections against executing data space. It is unreliable, non-portable and not recommended. But it does illustrate, if it works, that code and data are very similar.
I remember pulling a similar stunt between two processes, copying a function from one program into shared memory, and then having the other program execute that function from shared memory. It was about a quarter of a century ago, but the technique was similar and 'worked' for the machine it was tried on. I've never needed to use the technique since, thank goodness!
这段代码使用了未初始化的变量
_main
和_Demo
,因此它不能正常工作。即使它们的含义不同,它们也可能假定内存中函数的某些特定顺序。我的意见:不要相信这篇文章。
This code uses uninitialized variables
_main
and_Demo
, so it cannot work in general. Even if they meant something different, they probably assumed some specific ordering of functions in memory.My opinion: don't trust this article.