格式化字符串利用长度
Format string exploit length
我是软件安全方面的新手,现在正在大学学习。我对格式字符串漏洞利用有一些疑问,特别是如何计算格式字符串漏洞利用的长度(字节数)。
假设我有以下易受攻击的代码:
int guess(char *user) {
struct {
int n;
char usr[16];
char buf[16];
} s;
snprintf (s.usr, 16, "%s", user);
do {
scanf ("%s", s.buf);
if ( strncmp (s.buf, "DEBUG", 5) == 0) {
scanf ("%d", &s.n);
for ( int i = 0; i < s.n; i++) {
printf ("%x", s.buf[i]);
}
} else {
if ( strncmp (s.buf, "pass", 4) == 0 && s.usr[0] == '_') {
return 1;
} else {
printf ("Sorry User: ");
printf (s.usr); //#line 26 vulnerable line
printf ("\nThe secret is wrong! \n");
abort ();
}
}
} while ( strncmp (s.buf, "DEBUG", 5) == 0);
}
int main(int argc, char** argv) {
guess(argv[1]);
}
并且代码是在 IA-32 架构(32 位)中编译的,具有 cdecl 调用约定,并且没有实施攻击缓解(没有堆栈金丝雀,没有 ALSR 等......,我在一个完全易受攻击的机器中)
第 26 行存在格式字符串漏洞,因为缺少占位符 (printf (s.usr);
)。
我想用包含我的 shellcode 的环境变量地址覆盖 EIP。
我假设(这是一个理论练习,我知道在实践中还有许多其他含义)我的环境变量的地址是 0x44674234
,EIP 的地址是 0x42414515
并且我的格式字符串在堆栈上的位移是 7.
所以我的格式字符串利用将是 \x15\x45\x41\x42\x17\x45\x41\x42%16940c%7$hn%563c%8$hn
,我将把它放入 user
然后它会被复制到 s.usr
并由 printf (s.usr);
现在我注意到只有 15 个字符从 user
复制到 s.usr
。
我的格式字符串不可利用吗?我在我的 exploit 中计算了 30 个字符,因此 strcpy 将只复制我的 exploit 的一半。
我算的字数对吗?我应该如何计算它们?
\x15\x45\x41\x42\x17\x45\x41\x42%16940c%7$hn%563c%8$hn
确实指的是 30 chars/bytes 的序列。因此需要 snprintf (s.usr, 31, "%s", user);
来复制它。[1] 额外的计数是因为 snprintf
为 NUL 保留了 space。
由于您需要 s.usr
作为 30 个字符序列的开始,并且您只能在其中放置 15 个必要的字符,因此您的 exploit 无法按原样工作。
这并不意味着该漏洞无法被利用。可以编写一个更短的漏洞利用程序,跳转到位于其他地方的剩余漏洞利用程序,例如在 user
.[2] 但是我没有必要的知识来评估这个的可行性。
- 当然,你在
s.usr
中也需要更大的面积,至少在正常情况下是这样。
user
将包含 <15-byte exploit><remainder of exploit>
。 15 字节的漏洞将跳转到漏洞的其余部分。
我是软件安全方面的新手,现在正在大学学习。我对格式字符串漏洞利用有一些疑问,特别是如何计算格式字符串漏洞利用的长度(字节数)。
假设我有以下易受攻击的代码:
int guess(char *user) {
struct {
int n;
char usr[16];
char buf[16];
} s;
snprintf (s.usr, 16, "%s", user);
do {
scanf ("%s", s.buf);
if ( strncmp (s.buf, "DEBUG", 5) == 0) {
scanf ("%d", &s.n);
for ( int i = 0; i < s.n; i++) {
printf ("%x", s.buf[i]);
}
} else {
if ( strncmp (s.buf, "pass", 4) == 0 && s.usr[0] == '_') {
return 1;
} else {
printf ("Sorry User: ");
printf (s.usr); //#line 26 vulnerable line
printf ("\nThe secret is wrong! \n");
abort ();
}
}
} while ( strncmp (s.buf, "DEBUG", 5) == 0);
}
int main(int argc, char** argv) {
guess(argv[1]);
}
并且代码是在 IA-32 架构(32 位)中编译的,具有 cdecl 调用约定,并且没有实施攻击缓解(没有堆栈金丝雀,没有 ALSR 等......,我在一个完全易受攻击的机器中)
第 26 行存在格式字符串漏洞,因为缺少占位符 (printf (s.usr);
)。
我想用包含我的 shellcode 的环境变量地址覆盖 EIP。
我假设(这是一个理论练习,我知道在实践中还有许多其他含义)我的环境变量的地址是 0x44674234
,EIP 的地址是 0x42414515
并且我的格式字符串在堆栈上的位移是 7.
所以我的格式字符串利用将是 \x15\x45\x41\x42\x17\x45\x41\x42%16940c%7$hn%563c%8$hn
,我将把它放入 user
然后它会被复制到 s.usr
并由 printf (s.usr);
现在我注意到只有 15 个字符从 user
复制到 s.usr
。
我的格式字符串不可利用吗?我在我的 exploit 中计算了 30 个字符,因此 strcpy 将只复制我的 exploit 的一半。
我算的字数对吗?我应该如何计算它们?
\x15\x45\x41\x42\x17\x45\x41\x42%16940c%7$hn%563c%8$hn
确实指的是 30 chars/bytes 的序列。因此需要 snprintf (s.usr, 31, "%s", user);
来复制它。[1] 额外的计数是因为 snprintf
为 NUL 保留了 space。
由于您需要 s.usr
作为 30 个字符序列的开始,并且您只能在其中放置 15 个必要的字符,因此您的 exploit 无法按原样工作。
这并不意味着该漏洞无法被利用。可以编写一个更短的漏洞利用程序,跳转到位于其他地方的剩余漏洞利用程序,例如在 user
.[2] 但是我没有必要的知识来评估这个的可行性。
- 当然,你在
s.usr
中也需要更大的面积,至少在正常情况下是这样。 user
将包含<15-byte exploit><remainder of exploit>
。 15 字节的漏洞将跳转到漏洞的其余部分。