为什么将“extern puts”转换为函数指针“(void(*)(char*))&puts”?

2023-12-20

我正在看例子abo3.c http://community.corest.com/~gera/InsecureProgramming/abo3.html from 不安全编程 http://community.corest.com/~gera/InsecureProgramming我并没有在下面的例子中摸索演员阵容。有人可以启发我吗?

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 呢?

我真的很感谢对整个程序的解释,以正确地看待它。

[EDIT]
谢谢你们的意见!

乔纳森·莱夫勒 https://stackoverflow.com/users/15168/jonathan-leffler,代码“糟糕”实际上是有原因的。它应该是可利用的,溢出缓冲区和函数指针等。迷失网 http://mishou.org/2010/03/14/insecure-programming-by-example-abo3-c/有一篇关于如何利用上述代码的博客文章。其中很多仍然在我的脑海中。

bta https://stackoverflow.com/users/79566/bta,我从上面的博客文章中了解到,转换系统会以某种方式阻止链接器删除它。

目前尚不清楚的一件事是系统地址和放置地址都写入同一位置,我认为这可能就是 gera 所说的“因此链接器不会删除它”。

虽然我们正在讨论函数指针的主题,但既然语法更清晰了,我想问一个后续问题。我正在研究一些使用函数指针的更高级的示例,并偶然发现了这个令人厌恶的东西,它取自托管 shellcode 的网站。



#include <stdio.h>

char shellcode[] = "some shellcode";

int main(void)
{
    fprintf(stdout,"Length: %d\n",strlen(shellcode));
    (*(void(*)()) shellcode)();
}
  

所以数组被转换为返回的函数void、引用和调用?这看起来很糟糕——那么上面代码的目的是什么?

[/EDIT]


原问题

User bta https://stackoverflow.com/users/79566/bta对演员阵容给出了正确的解释 - 并评论了演员阵容的不恰当之处system.

我要补充一点:

The extern线条充其量是奇怪的。在严格的C99下是错误的,因为没有类型,这使得它无效;在 C89 下,类型将被假定为int。该行显示“有一个外部定义的整数称为 system,另一个称为 put”,这是不正确的 - 有一对具有这些名称的函数。该代码实际上可能“有效”,因为链接器可能会将函数与假定的整数相关联。但对于 64 位机器来说并不安全,因为指针的大小与int。当然,代码应该包含正确的标头(<stdio.h> for puts() and <stdlib.h> for system() and exit(), and <string.h> for strcpy()).

The exit(1);在两个不同的方面都是不好的。

  • 它无条件地表明失败。您可以使用 0 或EXIT_SUCCESS来表示成功。

  • 在我看来,最好使用return在......的最后main() than exit()。不一定每个人都同意我的观点,但我不喜欢看到exit()作为最后一行main()。唯一的借口是避免其他不良做法带来的问题,例如注册的函数atexit()这取决于定义在中的局部变量的持续存在main().


/usr/bin/gcc -g -std=c99 -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes -Wold-style-definition -c nasty.c
nasty.c: In function ‘main’:
nasty.c:3: warning: type defaults to ‘int’ in declaration of ‘system’
nasty.c:3: warning: type defaults to ‘int’ in declaration of ‘puts’
nasty.c:3: warning: built-in function ‘puts’ declared as non-function
nasty.c:8: warning: implicit declaration of function ‘strcpy’
nasty.c:8: warning: incompatible implicit declaration of built-in function ‘strcpy’
nasty.c:10: warning: implicit declaration of function ‘exit’
nasty.c:10: warning: incompatible implicit declaration of built-in function ‘exit’
nasty.c: At top level:
nasty.c:1: warning: unused parameter ‘argv’

不好的代码!我担心包含此类代码的信息源并不能解释所有的可怕之处(因为显示如此混乱的代码的唯一借口是剖析它并纠正它)。


代码中还有一个奇怪的地方:

int main(int argv,char **argc)   

这是“正确的”(它会起作用),但 100% 是传统的。正常的声明是:

int main(int argc, char **argv)

这些名称是“参数计数”和“参数向量”的缩写,并使用argc因为字符串向量(数组)的名称是不正常且完全令人困惑的。


访问所引用的站点后,您可以看到它正在经历一组分级示例。我不确定作者是否只是在 argc/argv 问题上有盲点或者故意搞乱('abo1' http://community.core-sdi.com/~gera/InsecureProgramming/abo1.html表明他正在玩,但在我看来这没有帮助)。这些示例应该可以满足您的需求,但对它们的作用没有太多解释。我不认为我可以推荐该网站。


延伸问题

这段代码中的强制转换在做什么?

#include <stdio.h>

char shellcode[] = "some shellcode";

int main(void)
{
    fprintf(stdout,"Length: %d\n",strlen(shellcode));
    (*(void(*)()) shellcode)();
}

它获取字符串“shellcode”的地址,并将其视为指向一个函数的指针,该函数接受一组不确定的参数,不返回任何值,并且不带参数执行它。该字符串包含某些漏洞利用的二进制汇编代码(通常运行 shell),入侵者的目标是获得 root 权限的程序来执行其 shellcode,并为他们提供具有 root 权限的命令提示符。从那时起,该系统就属于他们自己了。当然,为了练习,第一步是让一个非 root 程序来执行 shellcode。

回顾分析

分析于Mishou http://mishou.org/2010/03/14/insecure-programming-by-example-abo3-c/的网站并不像我希望的那样权威:

一、这段代码使用了C语言中的extern关键字来使system和put函数可用。它的作用(我认为)基本上是直接引用(隐含的)头文件中定义的函数的位置...我的印象是 GDB 会自动神奇地包含用于系统的头文件 stdlib.h 和用于 put 的头文件 stdio.h 。目前尚不清楚的一件事是系统地址和放置地址都写入同一位置,我认为这可能就是 gera 所说的“因此链接器不会删除它”。

剖析评论:

  1. 第一句话不太准确;它告诉编译器这些符号system and puts在其他地方定义(作为整数)。当代码链接时,地址为puts()- 函数已知;代码会将其视为整型变量,但整型变量的地址实际上是函数的地址 - 因此强制转换强制编译器将其视为函数指针。
  2. 第二句话不完全准确;链接器通过函数符号解析外部“变量”的地址system() and puts()在 C 库中。
  3. GDB 不执行任何编译或链接过程。
  4. 最后一句话根本没有任何意义。地址只会写入同一位置,因为您对同一变量进行了初始化和赋值。

必须说,这并没有促使我阅读整篇文章。尽职调查迫使我前进;后来的解释更好了,尽管仍然没有我想象的那么清楚。但是,使用过长但精心设计的参数字符串来溢出缓冲区的操作是该操作的核心。代码中提到了两者puts() and system()这样当在非利用模式下运行时,puts()函数是一个已知的符号(否则,你必须使用dlopen()找到它的地址),这样当在利用模式下运行时,代码具有符号system()可以直接使用。未使用的外部引用在可执行文件中不可用 - 当您意识到典型的系统标头中有多少个符号与包含标头的程序使用的符号数量相比,这是一件好事。

显示了一些巧妙的技巧 - 尽管这些技巧的实现没有显示在特定页面上;我假设(未经验证)信息为getenvaddr程序可用。

abo3.c代码可以写成:

#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”的准确警告。它与原始版本一样可被利用;但它是“更好”的代码,因为它编译干净。间接寻址是不必要的神秘,不是使代码可利用的关键部分。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么将“extern puts”转换为函数指针“(void(*)(char*))&puts”? 的相关文章

  • 成员字段、构建顺序

    在 C 中 当执行如下所示的操作时 构造顺序是否得到保证 Logger Logger kFilePath logs runtime log logFile kFilePath 是的 施工顺序始终得到保证 但是 不能保证它与对象在初始值设定项
  • 套接字编程-listen() 和accept() 有什么区别?

    我一直在读本教程 http www cs rpi edu moorthy Courses os98 Pgms socket html了解套接字编程 看来listen and accept 系统调用都做同样的事情 即阻塞并等待客户端连接到使用
  • C# - Visual Studio 中的 System.OutOfMemoryException

    我遇到问题 当我右键单击 Visual Studio 中的主窗体并转到 视图设计器 时 出现错误 它说 引发了 System OutOfMemoryException 类型的异常 堆栈跟踪 at System Reflection Asse
  • 如何使用最小起订量模拟私有只读 IList 属性

    我试图嘲笑这个列表 private readonly IList
  • 无需登录即可在 Intranet 上获取 Web 应用程序的域\用户名

    我的 Intranet 上有一个 Web 应用程序 VS 2005 有几个页面不需要用户登录应用程序 反馈和默认页面 我正在尝试获取要显示和 或发送反馈的域名和用户名 有没有一种方法可以在不需要用户登录的情况下执行此操作 我试过了this
  • BufferBlock 连续

    我想使用以下方式实现消费者 生产者模式BufferBlock
  • std::bind2nd 和 std::bind 与二维数组和结构数组

    我知道 C 有 lambda 并且 std bind1st std bind2nd 和 std bind 已弃用 然而 从C 的基础开始 我们可以更好地理解新特性 所以 我从这个非常简单的代码开始 使用int 数组s 第一个例子 与std
  • 何时使用 C++ 私有继承而不是组合?

    你能给我一个具体的例子吗 什么时候使用私有继承优于组合 就我个人而言 我将使用组合而不是私有继承 但在某些情况下 使用私有继承可能是特定问题的最佳解决方案 正在阅读C faq http www parashift com c faq lit
  • 如何部署包含第三方 DLL 文件的 C# 应用程序?

    首先 我对部署了解不多 我希望我的问题有意义 我需要将 C 应用程序安装 部署到多个桌面 它需要一个第三方 DLL 文件 一个 C 库 lpsolve55 dll 对于那些感兴趣的人 它是一个免费的 MIP LP 求解器 请参阅 lpsol
  • 如何在 ASP.NET Core 6.0 Web API 项目中启用 cors?

    在我的 ASP NET Core 6 0 Web API 项目中配置了 CORS 但预检请求收到 http 405 错误 换句话说 不允许使用 HTTP OPTION 看起来 cors 没有启用 我见过的例子config EnableCor
  • c 使用 lseek 以相反顺序复制文件

    我已经知道如何从一开始就将一个文件复制到另一个文件 但是我如何修改程序以按相反的顺序复制它 源文件应具有读取访问权限 目标文件应具有读写执行权限 我必须使用文件控制库 例如 FILE A File B should be ABCDEF FE
  • 根据 Active Directory 策略检查密码[重复]

    这个问题在这里已经有答案了 我有一个允许用户更改其 AD 密码的前端 有没有办法获取特定用户及其属性 长度 复杂性 的密码策略 例如细粒度 有没有办法根据此特定策略检查字符串 xyz121 编辑 我不想检查活动目录中存储的当前密码 我想检查
  • 原子的 C++ 内存屏障

    在这方面我是个新手 谁能提供以下内存屏障之间差异的简化解释 窗户MemoryBarrier 围栏 mm mfence 内联汇编asm volatile memory 内在的 ReadWriteBarrier 如果没有简单的解释 一些好文章或
  • 这些工作队列标志意味着什么?

    在研究工作队列时 我遇到了内核中定义的工作队列标志和常量 我有以下我无法理解的疑问 这里的排水和救援到底是什么意思 WQ DRAINING 1 lt lt 6 internal workqueue is draining WQ RESCUE
  • 如何在 ASP.NET Core 项目中使用 MStest 测试 Ok() 结果

    我正在使用 MStest 来测试我的控制器 我想测试这个动作 HttpGet Name GetGroups public async Task
  • Code::Blocks 中的调试似乎不起作用 - 缺少调试符号

    我正在尝试在 Code Blocks 中调试程序 我跟着本指南 http wiki codeblocks org index php title Debugging with Code Blocks and 这个短视频 http www y
  • 按 Enter 继续

    这不起作用 string temp cout lt lt Press Enter to Continue cin gt gt temp cout lt lt Press Enter to Continue cin ignore 或更好 in
  • C# 模式匹配

    我对 C 有点陌生 我正在寻找一个字符串匹配模式来执行以下操作 我有一个像这样的字符串 该书将在 唐宁街 11 号接待处 并将由主要医疗保健人员参加 我需要创建一个 span 标签来使用 startIndex 和 length 突出显示一些
  • 在两个点之间创建一条曲线,每个点都具有标准化向量

    因此 我需要一种写入方法来在两点之间创建一条曲线 每个点都有一个指向任意方向的归一化向量 我一直在尝试设计这样一种方法 但一直无法理解数学 在这里 由于一张图片胜过一千个文字 这就是我所需要的 在图中 矢量垂直于红线 我相信向量需要进行相同
  • 有没有办法在 C# 中仅通过文件名查找文件?

    我们现在使用绝对路径或相对路径在 C 应用程序中查找文件 如果文件位于当前工作目录下或 路径 之一下 有没有办法仅通过名称查找文件 使用绝对路径不好 使用相对路径也不够好 因为我们可能通过重命名或移动项目文件夹来更改项目结构 如果我们的代码

随机推荐

  • 您可以分配给父函数中定义的变量吗? [复制]

    这个问题在这里已经有答案了 可能的重复 Python 嵌套函数变量作用域 https stackoverflow com questions 5218895 python nested functions variable scoping
  • 如何在CSHTML文件中引用CSS?

    我如何申请 放置外部或额外的
  • 无法获取要触发的 ASIHTTPRequest 回调委托

    为什么我的回调委托没有触发 import dbConnector h import ASIFormDataRequest h import JSONKit h implementation dbConnector method to voi
  • 动态更改 jQuery 图像 src

    我只是想知道如何每 5 秒更改一次 src 我在用 backstretch site com images home5 jpg 是否可以像幻灯片一样将 home5 jpg 与其他图像 例如 home6 jpg 和 home7 jpg 交换
  • 如何在 HTML 中显示 Base64 图像

    我在内联显示 Base64 图像时遇到问题 我该怎么做 img style display block width 100px height 100px src 我的怀疑当然是实际的 Base64 数据 否则对我来说看起来很好 看这把小提琴
  • 在Objective C中,如何获取元类对象?

    In Objective C 如何获取元类对象 两个都 self class and ClassName class 仅返回 Class 对象 objc getMetaClass https developer apple com libr
  • 为什么活动开始时软键盘显示或不显示?

    当比较开发人员之间的设计时 我们发现了一个奇怪的行为 经过一番分析后 我们进行了这一观察 当活动开始时 在某些情况下键盘会出现 但有时不会 事实上 如果没有ScrollView 默认情况下软键盘不会出现在EditText
  • OSX 中的 tiff() 分辨率和压缩设置不可靠

    分辨率和压缩选项tiff 在我的系统上似乎被忽略 请参阅下面的信息 这似乎与中讨论的问题相同这个问题 https stackoverflow com questions 12609816 r tiff wont compress or se
  • Laravel + Image Intervention:强制下载未保存的文件

    我想简单地上传文件 调整它们的大小 然后强制下载每个上传的文件 我不想保存文件 调整大小等工作正常 但是我无法强制下载新文件 content image gt stream jpg return response gt download c
  • Quickblox 会话在后台过期。怎么处理呢?

    当用户进入后台时 我从聊天中注销该用户 当用户从后台返回时 我会在聊天中再次记录使用情况 这很有效 但并非每次都有效 有时 当用户将应用程序保持在后台超过 2 小时时 会话就会过期 并且当用户从后台返回时 会话似乎不会自动重新验证 即使使用
  • 编译 Java 类并从命令控制台运行 Java 文件时,如何包含 Java jar 文件?

    我有一个与 postgresql 数据库交互的小 Java 文件 所以我已经下载了驱动程序并在我的文件中导入org postgresql Driver 在命令控制台中我输入javac Myfilename java 然后它编译我运行java
  • JavaScript 异步/等待

    我正在尝试理解 JavaScript 异步 等待 如何重写以下内容 使输出为 Hi 然后 Bye 而不是 Bye 然后 Hi JSFiddle https jsfiddle net tp7tjhvL 1 sayHi then sayBye
  • 设置nginx支持自定义域名

    我有一个 Django Web 应用程序托管在一个虚拟机上 该虚拟机以基于 Debian 的 Ubuntu 作为操作系统 以 nginx 反向代理 Gunicorn 作为 Web 服务器 此 Web 应用程序的 DNS 是myapp clo
  • 如何以编程方式在 WordPress 中创建帖子 [关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions 我想知道如何在 WordPress
  • 我需要向父 div 添加一个像素

    我有一个 教室 的 div 其中包含每个 学生 的 div 每个 学生 div 都包含一个图像 这是 HTML div class classroom div class student img class student image sr
  • 需要 JQuery 弹出窗口/警报

    我有一个元素列表 每个元素需要有一个相应的弹出窗口 这不是背景变黑的弹出窗口 这更像是一个 JavaScript 警报 尽管我需要在弹出窗口中创建自己的样式按钮 并为其分配我们自己的定制事件 我需要每个弹出窗口将自己适当地放置在用户界面中相
  • 解析接受标头

    有人对解析 HTTP Accept 标头有任何建议 或正则表达式 吗 我正在尝试在 ASP NET MVC 中进行一些内容类型协商 似乎没有内置的方式 这很好 因为这里有很多思想流派 但是解析并不完全微不足道 如果有人已经完成了 我宁愿不重
  • 如何将字符串渲染为html链接

    我向电子邮件发送一些消息 如下所示 string link http localhost 1900 ResetPassword username user UserName reset HashResetParams user UserNa
  • IntelliJ IDEA v12 中的警告

    给出的答案为如何让Intellij Idea显示编译警告 https stackoverflow com questions 4745415 how to get intellij idea to display compilation w
  • 为什么将“extern puts”转换为函数指针“(void(*)(char*))&puts”?

    我正在看例子abo3 c http community corest com gera InsecureProgramming abo3 html from 不安全编程 http community corest com gera Inse