这是源码:
/* Bomb program that is solved using a buffer overflow attack */
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
/* Like gets, except that characters are typed as pairs of hex digits.
Nondigit characters are ignored. Stops when encounters newline */
char *getxs(char *dest)
{
int c;
int even = 1; /* Have read even number of digits */
int otherd = 0; /* Other hex digit of pair */
char *sp = dest;
while ((c = getchar()) != EOF && c != '\n') {
if (isxdigit(c)) {
int val;
if ('0' <= c && c <= '9')
val = c - '0';
else if ('A' <= c && c <= 'F')
val = c - 'A' + 10;
else
val = c - 'a' + 10;
if (even) {
otherd = val;
even = 0;
} else {
*sp++ = otherd * 16 + val;
even = 1;
}
}
}
*sp++ = '\0';
return dest;
}
/* $begin getbuf-c */
int getbuf()
{
char buf[12];
getxs(buf);
return 1;
}
void test()
{
int val;
printf("Type Hex string:");
val = getbuf();
printf("getbuf returned 0x%x\n", val);
}
/* $end getbuf-c */
int main()
{
int buf[16];
/* This little hack is an attempt to get the stack to be in a
stable position
*/
int offset = (((int) buf) & 0xFFF);
int *space = (int *) alloca(offset);
*space = 0; /* So that don't get complaint of unused variable */
test();
return 0;
}
想办法让test的printf语句不返回1,其实 可以指定返回内容:D
恩,首先 既然是用缓冲区溢出的漏洞,那要先了解stack frame的结构,反汇编必不可少了
gcc -o dis_buff.s -S buff.c
.file "buff.c"
.text
.globl getxs
.type getxs, @function
getxs:
pushl %ebp
movl %esp, %ebp
subl $40, %esp
movl $1, -16(%ebp)
movl $0, -20(%ebp)
movl 8(%ebp), %eax
movl %eax, -24(%ebp)
jmp .L2
.L8:
call __ctype_b_loc
movl (%eax), %eax
movl -12(%ebp), %edx
addl %edx, %edx
addl %edx, %eax
movzwl (%eax), %eax
movzwl %ax, %eax
andl $4096, %eax
testl %eax, %eax
je .L2
cmpl $47, -12(%ebp)
jle .L3
cmpl $57, -12(%ebp)
jg .L3
movl -12(%ebp), %eax
subl $48, %eax
movl %eax, -28(%ebp)
jmp .L4
.L3:
cmpl $64, -12(%ebp)
jle .L5
cmpl $70, -12(%ebp)
jg .L5
movl -12(%ebp), %eax
subl $55, %eax
movl %eax, -28(%ebp)
jmp .L4
.L5:
movl -12(%ebp), %eax
subl $87, %eax
movl %eax, -28(%ebp)
.L4:
cmpl $0, -16(%ebp)
je .L6
movl -28(%ebp), %eax
movl %eax, -20(%ebp)
movl $0, -16(%ebp)
jmp .L2
.L6:
movl -20(%ebp), %eax
movl %eax, %edx
sall $4, %edx
movl -28(%ebp), %eax
leal (%edx,%eax), %eax
movl %eax, %edx
movl -24(%ebp), %eax
movb %dl, (%eax)
addl $1, -24(%ebp)
movl $1, -16(%ebp)
.L2:
call getchar
movl %eax, -12(%ebp)
cmpl $-1, -12(%ebp)
je .L7
cmpl $10, -12(%ebp)
jne .L8
.L7:
movl -24(%ebp), %eax
movb $0, (%eax)
addl $1, -24(%ebp)
movl 8(%ebp), %eax
leave
ret
.size getxs, .-getxs
.globl getbuf
.type getbuf, @function
getbuf:
pushl %ebp
movl %esp, %ebp
subl $40, %esp
movl %gs:20, %eax
movl %eax, -12(%ebp)
xorl %eax, %eax
leal -24(%ebp), %eax
movl %eax, (%esp)
call getxs
movl $1, %eax
movl -12(%ebp), %edx
xorl %gs:20, %edx
je .L12
call __stack_chk_fail
.L12:
leave
ret
.size getbuf, .-getbuf
.section .rodata
.LC0:
.string "Type Hex string:"
.LC1:
.string "getbuf returned 0x%x\n"
.text
.globl test
.type test, @function
test:
pushl %ebp
movl %esp, %ebp
subl $40, %esp
movl $.LC0, %eax
movl %eax, (%esp)
call printf
call getbuf
movl %eax, -12(%ebp)
movl $.LC1, %eax
movl -12(%ebp), %edx
movl %edx, 4(%esp)
movl %eax, (%esp)
call printf
leave
ret
.size test, .-test
.globl main
.type main, @function
main:
leal 4(%esp), %ecx
andl $-16, %esp
pushl -4(%ecx)
pushl %ebp
movl %esp, %ebp
pushl %ecx
subl $84, %esp
movl %gs:20, %eax
movl %eax, -12(%ebp)
xorl %eax, %eax
leal -84(%ebp), %eax
andl $4095, %eax
movl %eax, -16(%ebp)
movl -16(%ebp), %eax
addl $15, %eax
addl $15, %eax
shrl $4, %eax
sall $4, %eax
subl %eax, %esp
movl %esp, %eax
addl $15, %eax
shrl $4, %eax
sall $4, %eax
movl %eax, -20(%ebp)
movl -20(%ebp), %eax
movl $0, (%eax)
call test
movl $0, %eax
movl -12(%ebp), %edx
xorl %gs:20, %edx
je .L17
call __stack_chk_fail
.L17:
movl -4(%ebp), %ecx
leave
leal -4(%ecx), %esp
ret
.size main, .-main
.ident "GCC: (Ubuntu/Linaro 4.4.4-14ubuntu5) 4.4.5"
.section .note.GNU-stack,"",@progbits
有了反汇编之后,发现诡异的几行:85,93,135,157出现了个诡异的%gs:20以及个诡异的函数__stack_chk_fail.
查阅资料后,了解到__stack_chk_fail是GCC较新版本的一个栈保护的函数,大概的原理是通过调用在调用对栈可能构成危险的函数前存入一个特殊的值%gs:20并放如当前栈中,在函数调用结束后,用__stack_chk_fail函数对该特殊值进行检查该特殊值是否被改变,若改变,则栈被破坏。所以,目前__stack_chk_fail也是个阻碍,为了方便,暂时先不需要理会这个gcc的栈保护机制。
所以,目前重点研究的汇编代码如下:
gcc -fno-stack-protector -o dis_buff_nochk.s -S buff.c
.file "buff.c"
.text
.globl getxs
.type getxs, @function
getxs:
pushl %ebp
movl %esp, %ebp
subl $40, %esp
movl $1, -24(%ebp)
movl $0, -20(%ebp)
movl 8(%ebp), %eax
movl %eax, -16(%ebp)
jmp .L2
.L8:
call __ctype_b_loc
movl (%eax), %eax
movl -28(%ebp), %edx
addl %edx, %edx
addl %edx, %eax
movzwl (%eax), %eax
movzwl %ax, %eax
andl $4096, %eax
testl %eax, %eax
je .L2
cmpl $47, -28(%ebp)
jle .L3
cmpl $57, -28(%ebp)
jg .L3
movl -28(%ebp), %eax
subl $48, %eax
movl %eax, -12(%ebp)
jmp .L4
.L3:
cmpl $64, -28(%ebp)
jle .L5
cmpl $70, -28(%ebp)
jg .L5
movl -28(%ebp), %eax
subl $55, %eax
movl %eax, -12(%ebp)
jmp .L4
.L5:
movl -28(%ebp), %eax
subl $87, %eax
movl %eax, -12(%ebp)
.L4:
cmpl $0, -24(%ebp)
je .L6
movl -12(%ebp), %eax
movl %eax, -20(%ebp)
movl $0, -24(%ebp)
jmp .L2
.L6:
movl -20(%ebp), %eax
movl %eax, %edx
sall $4, %edx
movl -12(%ebp), %eax
leal (%edx,%eax), %eax
movl %eax, %edx
movl -16(%ebp), %eax
movb %dl, (%eax)
addl $1, -16(%ebp)
movl $1, -24(%ebp)
.L2:
call getchar
movl %eax, -28(%ebp)
cmpl $-1, -28(%ebp)
je .L7
cmpl $10, -28(%ebp)
jne .L8
.L7:
movl -16(%ebp), %eax
movb $0, (%eax)
addl $1, -16(%ebp)
movl 8(%ebp), %eax
leave
ret
.size getxs, .-getxs
.globl getbuf
.type getbuf, @function
getbuf:
pushl %ebp
movl %esp, %ebp
subl $40, %esp
leal -20(%ebp), %eax
movl %eax, (%esp)
call getxs
movl $1, %eax
leave
ret
.size getbuf, .-getbuf
.section .rodata
.LC0:
.string "Type Hex string:"
.LC1:
.string "getbuf returned 0x%x\n"
.text
.globl test
.type test, @function
test:
pushl %ebp
movl %esp, %ebp
subl $40, %esp
movl $.LC0, %eax
movl %eax, (%esp)
call printf
call getbuf
movl %eax, -12(%ebp)
movl $.LC1, %eax
movl -12(%ebp), %edx
movl %edx, 4(%esp)
movl %eax, (%esp)
call printf
leave
ret
.size test, .-test
.globl main
.type main, @function
main:
leal 4(%esp), %ecx
andl $-16, %esp
pushl -4(%ecx)
pushl %ebp
movl %esp, %ebp
pushl %ecx
subl $84, %esp
leal -80(%ebp), %eax
andl $4095, %eax
movl %eax, -16(%ebp)
movl -16(%ebp), %eax
addl $15, %eax
addl $15, %eax
shrl $4, %eax
sall $4, %eax
subl %eax, %esp
movl %esp, %eax
addl $15, %eax
shrl $4, %eax
sall $4, %eax
movl %eax, -12(%ebp)
movl -12(%ebp), %eax
movl $0, (%eax)
call test
movl $0, %eax
movl -4(%ebp), %ecx
leave
leal -4(%ecx), %esp
ret
.size main, .-main
.ident "GCC: (Ubuntu/Linaro 4.4.4-14ubuntu5) 4.4.5"
.section .note.GNU-stack,"",@progbits