Size Is Important

Size Is Important

According to the statistics, the size of most overflowing buffers is 8 bytes. Buffers from 16 to 128 (or even 512) bytes in size are considerably less susceptible to overflow. Larger buffers are practically never encountered in real-world applications.

Relying on the worst-case scenario (and, under field conditions, the attacker must proceed exactly this way), hackers try to learn how to survive even in the most severe and aggressive environment. If hackers choose a creative approach and use their brains , it will be possible to fit much within the small overflowing buffer.

The first and simplest approach that came to mind to the predecessors of contemporary hackers was splitting the attacking program into two unequal parts ” a compact head and a long tail. The head ensures the following functions: overflowing of the buffer, capturing of control, and loading of the tail. The head can carry binary code but also might do without it, carrying out all malicious activity using the functionality of the vulnerable program. Many programs contain a large number of auxiliary functions that provide full control over the system, or at least allow hackers to wreck them and put them under hacker control. Modification of one or more crucial cells of the program immediately crashes it, and the number of modified cells begins to grow exponentially. The values required by the intruder, after a short cause ”effect chain of events, are loaded into the key cells of the program. The intricate pattern of the garbage bytes suddenly forms a beautiful combination, after which the lock clicks and the door of the safe slowly opens. This is similar to a chess game, which requires the player to declare checkmate within N moves even though the values of most fields are unknown. Therefore, the complexity of the problem grows rapidly with the increasing value of N .

It is extremely difficult to provide individual examples of puzzles, because even the simplest of them take several pages printed in small fonts ( otherwise , listings appear artificial and the solution seems self-evident). If you are interested in this topic, I recommend that you consider the code of the Slapper worm, which remains the indisputable leader in this balancing act. This code was analyzed in detail by the specialists from Symantec (see "An Analysis of the Slapper Worm Exploit" on their site at http://securityresponse.symantec.com/avcenter/reference/analysis.slapper.worm.pdf ) .

Nevertheless, attacks of this type are related more to exotic intellectual puzzles that to practical techniques of intrusion. Therefore, they are rarely encountered. Getting back to the traditional intrusion tools, note that if the size of the overflowing buffer equals 8 bytes, this doesn't necessarily mean that the length of the shellcode equals the same 8 bytes. After all, this buffer must overflow. However, rushing to another extreme and hoping that the maximum allowed length of the shellcode will be practically unlimited is wrong. Most vulnerable applications contain several levels that check the user input for correctness. Although these checks are not implemented quite correctly, they still impose limitations on the attack, and sometimes these limitations are quite stringent.

If the loader cannot fit within the small overflowing buffer, then the attacker begins to act according to plan B, searching for alternative methods of passing the shellcode. Assume that one of the fields of the user data packets allows overflow, resulting the capturing of control. Its size is catastrophically small; however, all other fields are also contained in the main memory. Therefore, nothing can prevent the attacker from using them for passing the shellcode. The overflowing buffer, influencing the system in some way, instead of passing control to its own starting point must pass control to the first byte of the shellcode, provided that the attacker knows the relative or absolute address of the shellcode in the main memory. Because the simplest method of passing control to automatic buffers is reduced to the jmp esp instruction, the most convenient technique is inserting the shellcode into those buffers located directly near the stack top. Otherwise, there is a risk of the situation rushing out of control, in which case the attacker will have to spend considerable time and effort to create reliable shellcode. In general, the shellcode can be found in the most unexpected locations, for example, in the tail of the last TCP packet (in most cases, it falls into the address space of a vulnerable process and is often located at predictable addresses).

In more difficult cases, shellcode can be passed in a separate session, in which case the intruder creates several connections to the server. The shellcode is passed through one of these connections (without overflow, but in those fields, the size of which is sufficient to hold the shellcode). Another connection passes the query that causes the overflow and passes control to the shellcode. The point is that in multithreaded applications, local stacks of all threads are located in the common address space of the process, and their addresses are assigned in an ordered manner, not chaotically. Provided that nobody else has connected to the server between the last two connections created by the intruder, the determination of addresses, taking into account multithreading, is a complicated but not an unsolvable task.



Shellcoder's Programming Uncovered
Shellcoders Programming Uncovered (Uncovered series)
ISBN: 193176946X
EAN: 2147483647
Year: 2003
Pages: 164

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net