//csdn博客目前暂时不再更新了,有兴趣请访问我的技术博客-晓的博客:zhangxiaolong.org
今天做格式化字符串漏洞实验。是一个比较有难度的实验,这也是下一个shellcode实验的基础。
首先呢,要了解一下我们将会用到的知识(以我的预习情况来给大家做知识讲解):
(1)给出以下程序:
main()
{
int num=0x41414141;
printf("Before: num = %#x \n", num);
printf("%.20d%hn\n", num, &num);
printf("After: num = %#x \n", num);
}
查看这段代码的执行结果,解释%.20d和%hn的含义。
经过运行输出为:
Before:num=0x41414141
00000000001094795585
After : num= 0x4141001a
解释:
%.20d:%m.n格式中m为输出宽度,n为精度控制。d表示以十进制形式输出带符号整数,所以解释是为输出精度为20的整形量。
%hn: h表示按短整型量输出,%n 并不告诉printf()显示什么内容,而是将已输出的字符个数放入到变元指向的变量中。在printf()调用返回后,这个变量将包含一个遇到%n是字符输出的数目。
(2)解释linux用root执行下面这条命令sysctl -w kernel.randomize_va_space=0的含义和用途。
解答:
Sysctl:sysctl is an interface that allows you to make changes to a running Linux kernel. With /etc/sysctl.conf you can configure various Linux networking and system settings such as:
1. Limit network-transmitted configuration for IPv4
2. Limit network-transmitted configuration for IPv6
3. Turn on execshield protection
4. Prevent against the common 'syn flood attack'
5. Turn on source IP address verification
6. Prevents a cracker from using a spoofing attack against the IP address of the server.
7. Logs several types of suspicious packets, such as spoofed packets, source-routed packets, and redirects.
sysctl -w kernel.randomize_va_space=0 表示关掉aslr功能,ASLR(Address space layout randomization)是一种针对缓冲区溢出的安全保护技术,通过对栈、共享库映射等线性区布局的随机化,防止攻击者定位攻击代码位置,达到阻止溢出攻击的目的。
经过这两个小问题的学习之后,我们要了解Format String Vulnerability的实验的要求(这实验任务书是英文的,我就偷个懒,就不翻译了,不过应该很容易看懂的):
In the following program, you will be asked to provide an input, which will be saved in a buffer calleduser input. The program then prints out the buffer using printf. The program is a Set-UID program(the owner is root), i.e., it runs with the root privilege. Unfortunately, there is a format-string vulnerabilityin the way how the printf is called on the user inputs. We want to exploit this vulnerability and see howmuch damage we can achieve.
The program has two secret values stored in its memory, and you are interested in these secret values.However, the secret values are unknown to you, nor can you find them from reading the binary code (forthe sake of simplicity, we hardcode the secrets using constants 0x44 and 0x55). Although you do not knowthe secret values, in practice, it is not so difficult to find out the memory address (the range or the exactvalue) of them (they are in consecutive addresses), because for many operating systems, the addresses areexactly the same anytime you run the program. In this lab, we just assume that you have already known theexact addresses. To achieve this, the program “intentionally” prints out the addresses for you.
With suchknowledge, your goal is to achieve the followings (not necessarily at the same time)Crash the program .
_ Print out the secret[0] value.
_ Modify the secret[0] value.
_ Modify the secret[0] value to a pre-determined value.
Note that the binary code of the program (Set-UID) is only readable/executable by you, and there isno way you can modify the code. Namely, you need to achieve the above objectives without modifying thevulnerable code. However, you do have a copy of the source code, which can help you design your attacks.
总体来说,需要做以下任务:
1. 指出cret[0]中的值;
2. 修改cret[0]中的值;
3. 更改secret[0]的值为设计好的数值。
实验过程步骤:
(1)在linux中要关掉内存随机化分配的功能,指令如下:
sysctl -w kernel.randomize_va_space=0
(2) 编写root程序vulp.c,vulp.c程序为(这个程序就是我们用printf格式化字符串攻击的程序):
/* vul_prog.c */ #define SECRET1 0x44 #define SECRET2 0x55 int main(int argc, char *argv[]) { char user_input[100]; int *secret; int int_input; int a, b, c, d; /* other variables, not used here.*/ /* The secret value is stored on the heap */ secret = (int *) malloc(2*sizeof(int)); /* getting the secret */ secret[0] = SECRET1; secret[1] = SECRET2; printf("The variable secret's address is 0x%8x (on stack)\n", &secret); printf("The variable secret's value is 0x%8x (on heap)\n", secret); printf("secret[0]'s address is 0x%8x (on heap)\n", &secret[0]); printf("secret[1]'s address is 0x%8x (on heap)\n", &secret[1]); printf("Please enter a decimal integer\n"); scanf("%d", &int_input); /* getting an input from user */ printf("Please enter a string\n"); scanf("%s", user_input); /* getting a string from user */ /* Vulnerable place */ printf(user_input); printf("\n"); /* Verify whether your attack is successful */ printf("The original secrets: 0x%x -- 0x%x\n", SECRET1, SECRET2); printf("The new secrets: 0x%x -- 0x%x\n", secret[0], secret[1]); return 0; }
编译vulp.c程序,设置为suid权限,并以用户权限执行这段程序。输入一个用于定位的数值,例如输入25,在机器中十六进制为00000019,在输入一个字符串%08x. %08x. %08x. %08x. %08x. %08x. %08x. %08x. %08x. %08x. %08x. %08x.用以输出堆栈中此时的数值,可以看到我们自己的数值0x19的位置。如下图所示。
(3)更改secret[0]中值。首先要确定这个数值的地址。可以在上图看到地址为0x804b008,换算为十进制数为134524936,故在要求输入数值时输入134524936,此数值换为十六进制为我们要写入的地址,即secret[0]。更改这个地址的内容。如图所示:
(4)更改secret[0]中的值为指定的数值,进行漏洞攻击。前面如(3)所示,要在secret[0]中写入0x1234替换原来的0x44,0x1234换算为十进制数为4660,计算位置数值为8×9=72,即4660=72+4588,所以要填补4588个0,才能保证secret[0]中为0x1234.如下两图所示。