问题描述
我在查看 =http://community.corest.com/~gera/InsecureProgramming =nofollow>不安全的编程,我不是grokking的铸造在下面的例子。
I'm looking at example abo3.c from Insecure Programming and I'm not grokking the casting in the example below. Could someone enlighten me?
int main(int argv,char **argc) { extern system,puts; void (*fn)(char*)=(void(*)(char*))&system; char buf[256]; fn=(void(*)(char*))&puts; strcpy(buf,argc[1]); fn(argc[2]); exit(1); }
所以 - 系统和货币的投资是什么?它们都返回一个 int 所以为什么把它转换为void?
So - what's with the casting for system and puts? They both return an int so why cast it to void?
我真的很感激整个程序的解释,以透视。
I'd really appreciate an explanation of the whole program to put it in perspective.
感谢您的意见!
Thank you both for your input!
,实际上有一个原因代码是坏。它应该是可利用的,溢出缓冲区和函数指针等。有一篇博文,介绍如何利用上述代码。很多它仍然在我的头上。
Jonathan Leffler, there is actually a reason for the code to be 'bad'. It's supposed to be exploitable, overflowing buffers and function pointers etc. mishou.org has a blog post on how to exploit the above code. A lot of it is still above my head.
,我从上面的博文中收集到系统会以某种方式阻止链接器删除它。
bta, I gather from the above blog post that casting system would somehow prevent the linker from removing it.
虽然我们的主题的函数指针, d现在想问一个后续问题的语法更清楚。我正在看一些更高级的例子使用函数指针,偶然在这可憎的,从站点托管shellcode。
While we are on the subject of function pointers, I'd like to ask a follow-up question now that the syntax is clearer. I was looking at some more advanced examples using function pointers and stumbled upon this abomination, taken from a site hosting shellcode.
#include <stdio.h> char shellcode[] = "some shellcode"; int main(void) { fprintf(stdout,"Length: %d\n",strlen(shellcode)); (*(void(*)()) shellcode)(); }
所以数组被转换为一个函数返回 void ,引用和调用?
So the array is getting cast to a function returning void, referenced and called? That just looks nasty - so what's the purpose of the above code?
[/ EDIT]
推荐答案
原始问题
用户表明他在玩,但它在我看来没有帮助)。例子应该是你的想法,但没有太多的解释他们做什么。我不认为我可以推荐该网站。
Having visited the site referenced, you can see that it is going through a set of graduated examples. I'm not sure whether the author simply has a blind spot on the argc/argv issue or is deliberately messing around ('abo1' suggests that he is playing, but it is not helpful in my view). The examples are supposed to feed your mind, but there isn't much explanation of what they do. I don't think I could recommend the site.
#include <stdio.h> char shellcode[] = "some shellcode"; int main(void) { fprintf(stdout,"Length: %d\n",strlen(shellcode)); (*(void(*)()) shellcode)(); }
这需要字符串'shellcode'的地址,到一个函数,它接受一个不确定的参数集,并返回没有值,并且没有参数执行它。该字符串包含一些exploit的二进制汇编代码 - 通常运行shell - 并且入侵者的目标是获得一个root特权程序来执行他们的shellcode并给他们一个命令提示符,具有root权限。从那里,系统是他们的拥有。
This takes the address of the string 'shellcode' and treats it as a pointer to a function that takes an indeterminate set of arguments and returns no values and executes it with no arguments. The string contains the binary assembler code for some exploit - usually running the shell - and the objective of the intruder is to get a root-privileged program to execute their shellcode and give them a command prompt, with root privileges. From there, the system is theirs to own. For practicing, the first step is to get a non-root program to execute the shellcode, of course.
在的网站上进行的分析不像我想要的那样权威:
The analysis at Mishou's web site is not as authoritative as I'd like:
解释评论:
- 第一句话不是很准确;它告诉编译器符号 system 和 puts 在其他地方定义(作为整数)。当代码被链接时, puts()的函数的地址是已知的;代码将把它当作一个整数变量,但是整数变量的地址实际上是函数的地址 - 所以强制转换强制编译器把它作为一个函数指针。
- 第二句话不完全准确;链接器通过函数符号 system()和 puts()解析外部变量的地址C库。
- GDB没有任何编译或链接过程。
- 最后一句没有任何意义。
- The first sentence isn't very accurate; it tells the compiler that the symbols system and puts are defined (as integers) somewhere else. When the code is linked, the address of puts()-the-function is known; the code will treat it as an integer variable, but the address of the integer variable is, in fact, the address of the function - so the cast forces the compiler to treat it as a function pointer after all.
- The second sentence is not fully accurate; the linker resolves the addresses of the external 'variables' via the function symbols system() and puts() in the C library.
- GDB has nothing whatsoever to do the compilation or linking process.
- The last sentence does not make any sense at all. The addresses only get written to the same location because you have an initialization and an assignment to the same variable.
这并没有激励我们的地址只能写入相同的位置,因为它有一个初始化和赋值给同一个变量。我读整篇文章,一定要说。尽职调查迫使我向前;后来的解释更好,虽然仍然不是那么清楚,我认为它可以是。但是,用一个超长但精心设计的参数字符串溢出缓冲区的操作是操作的核心。代码提到 puts()和 system(),以便在非漏洞模式下运行时, puts()函数是一个已知符号(否则,你必须使用 dlopen()找到它的地址)并且因此在exploit模式下运行时,代码具有可以直接使用的符号 system()。未使用的外部引用在可执行文件中不可用 - 当你意识到在一个典型的系统标题中有多少个符号,与包含头的程序所使用的数字相比,这是一件好事。
This didn't motivate me to read the whole article, it must be said. Due diligence forces me onwards; the explanation afterwards is better, though still not as clear as I think it could be. But the operation of overflowing the buffer with an overlong but carefully crafted argument string is the core of the operation. The code mentions both puts() and system() so that when run in non-exploit mode, the puts() function is a known symbol (otherwise, you'd have to use dlopen() to find its address), and so that when run in exploit mode, the code has the symbol system() available for direct use. Unused external references are not made available in the executable - a good thing when you realize how many symbols there are in a typical system header compared with the number used by a program that includes the header.
有一些简单的技巧显示 - 虽然这些技巧的实现没有显示在特定的页面上;我假设(未经验证) getenvaddr 程序的信息可用。
There are some neat tricks shown - though the implementation of those tricks is not shown on the specific page; I assume (without having verified it) that the information for getenvaddr program is available.
abo3.c代码可以写成:
The abo3.c code can be written as:
#include <stdio.h> #include <stdlib.h> #include <string.h> int main(int argc, char **argv) { void (*fn)(char*) = (void(*)(char*))system; char buf[256]; fn = (void(*)(char*))puts; strcpy(buf, argv[1]); fn(argv[2]); exit(1); }
现在它只编译一个警告与我最初使用的繁琐的编译选项 - 这是'argc'不使用的准确警告。它与原来一样可以利用;它是'更好的'代码,因为它编译干净。间接是不必要的神秘,不是使代码可利用的关键部分。
Now it compiles with only one warning with the fussy compilation options I originally used - and that's the accurate warning that 'argc' is not used. It is just as exploitable as the original; it is 'better' code though because it compiles cleanly. The indirections were unnecessary mystique, not a crucial part of making the code exploitable.
这篇关于为什么铸造“外部放置”到函数指针“(void(*)(char *))& puts”?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!