den RIP bestimmen (shellcode) - eine unklarheit

schon wieder ich :)

wie der betreff es schon sagt, geht es mir momentan um die bestimmung der rücksprungadresse. ich verstehe soweit warum man ausreichend NOPs vor dem eigentlich shellcode hinzufügen solle. nun treffe ich bei so gut wie allen texten, die ich zu diesem thema durchgelesen habe, auf folgendes programm zur "abschätzung" der adresse, wohin gesprungen werden soll:

Code:
sp.c
------------------------------------------------------------------------------
unsigned long get_sp(void) {
   __asm__("movl %esp,%eax");
}
void main() {
  printf("0x%x\n", get_sp());
}

Quelle: http://www.phrack.org/phrack/49/P49-14

was ich mich jetzt frage ist: inwiefern ist die zurückgegebene adresse relevant für das auszunutzende programm? also dieses programm "sp" läuft ja in seiner eigenen umgebung ab. wenn ich "sp" starte und es mir die adresse ausgibt, hab ich doch den stack-pointer von "sp" und nicht von dem programm, in dessen puffer der shellcode reinkommt. inwiefern haben sie überhaupt miteinander zu tun? mein verständnis der sache ist bis jetzt so, dass der stack des einen programms nichts mit dem anderen zu tun hat - ausser dass die anfangsadresse für beide dieselbe ist. warum ist dann die ausgabe dieser adresse für das andere übertragbar oder besser gesagt benutzbar (und irgendwie relevant)?

und wenn es doch miteinander zu tun hat: wie kommt es? ist diese methode der "bestimmung" des RIP demnach nur für einen lokalen exploit zu gebrauchen - dass also beide programme auf demselben rechner laufen müssen? fragen über fragen. wenn jemand da eine antwort weiß oder einen link speziell hierzu kennt, wäre es klasse, wenn ich diese infos bekommen könnte.

nur noch einmal zur verdeutlichung: es geht nicht um das allgemenite shellcode-howto, sondern speziell um diese funktion wie sie in vielen tutorials und büchern benutzt wird, mir jedoch im moment der hintergrund nicht klar ist WARUM es so funktioniert.

grüße,
alpha.
 
The problem we are faced when trying to overflow the buffer of another
program is trying to figure out at what address the buffer (and thus our
code) will be. The answer is that for every program the stack will
start at the same address. Most programs do not push more than a few hundred
or a few thousand bytes into the stack at any one time.
Therefore by knowing
where the stack starts we can try to guess where the buffer we are trying to
overflow will be. Here is a little program that will print its stack
pointer:


Die Absicht ist hier, rauszufinden, wo die startadresse des Stacks liegt ;). Wie Du richtig erkannt hast, sollte es nur auf dem Localsystem gleich sein und zumindest bei Windows muss es nicht zwingend gleich sein, sondern hängt auch von der Linkeroption an (z.B sektionsanordnung, Stackgröße).Hier soll ja auch ein anderes Programm "overflowed" werden. Aber es geht hier weiter, Sinn ergibt das Ganze erst hier:
addr = get_sp() - offset;
man versucht damit seine absolute Adresse herauszufinden.
So wie ich das sehe ist es eine Art Tutorial wo man selber noch was mitlernt und verschiedene Vorgensweisen dargelegt werden denn:
The problem is we need to guess *exactly* where the address of our
Und das Programm mit der Anweisung ist extra dafür um als Beispiel zu fungieren, dass z.B man genau die Stelle kennen muss, wohin man "Returnt" um im Shellcode zu landen. Landet man mitten drin, so kann es entweder eine "illegal instruction" geben (man landet dabei mitten in einem Opcode und die CPU versucht dann einen Teil davon munter auszuführen - entweder klappts gar nicht oder es macht was ganz anderes. Beispiel, unser Shellcode beginnt mit EB 4C = Jmp 4C Bytes weiter (um z.B bestimmte Routine zu überspringen). Landet man beim Rücksprung aber ein Byte "zu kurz" ließt die CPU stattdessen nur noch 4C ein, und das ist (zufällig) DEC ESP)
Zurück zu deiner Frage: so wie ichs verstanden habe, ist es nur ein Beispiel um die Stackfunktionsweise und die Interaktion zu erläutern.
In dem Beispiel demonstriert er (wenn ich das jetzt auf die schnelle und ohne Unix/C-Kenntisse richtig interpretiert hab ;) ), dass man nicht einfach die Rücksprungadresse mehrfach wiederholen kann im Buffer um dann automatisch im Shellcode landen, sondern dass es dabei auch zu Fehlern kommen kann - und warum man besser NOP verwendet. Um auf movl %esp,%eax zurückzukommen, diese wird benutzt um die Offsetangebe mittels Parametern machen zu können - z.B bei Programm buffergröße, Offset=100 landet man nicht im Speicher 100 sondern 100Bytes nach dem Stackanfang.
 
wieder cdw, und wieder danke :)

also für mich waren jetzt deine ersten sätze von großer bedeutung. dann wird also wirklich einfach davon ausgegangen, wenn das eine programm ungefährt an der adresse xy den stack-pointer hat, dann hat ein anderes auf diesem rechner ausgeführte auch ungefähr dieselbe adresse. gut zu wissen :) also mir ist schon klar, dass das nicht wirklich sicher ist aber deine erklärung weiter untetn hat es nocheinmal verdeutlicht. ich glaube so wird das auch vollkommen klar, dass man da noch u.u. hunderte von NOPs davor schriebt - oder besser gesagt soviele dass der eigentliche shellcode noch reinpasst und der buffer ja selbst in richtung stack-spitze nicht überschritten werden kann. vielen dank für wiederholte hilfreiche antwort. dann kann ich jetzt auch wieder weitermachen im text :)

grüße,
ela.
 
Original von alpha
also für mich waren jetzt deine ersten sätze von großer bedeutung. dann wird also wirklich einfach davon ausgegangen, wenn das eine programm ungefährt an der adresse xy den stack-pointer hat, dann hat ein anderes auf diesem rechner ausgeführte auch ungefähr dieselbe adresse. gut zu wissen :)

so kann mans wohl auch machen, aber in der regel schreibt man die funktion get_sp() in den exploit code und da wird ja dann oft am ende ein exec() syscall gemacht um das zu exploitende program auszufuehren (bei nem lokalen exploit versteht sich).
d.h. das zu exploitende programm wird in den bereich geladen wo vorher das exploitprogramm lief. dadurch hat das zielprogramm genau den stack pointer den der exploit vorher mit get_sp() ermittelt hat.
 
aber in der regel schreibt man die funktion get_sp() in den exploit code
nene, hier ist ein anderer Zusammenhang - und zwar die RET Adresse. Im Code wird diese eben so ermittelt (klappt damit auch nur für so ein einfaches Programm) dass sie auf den Stackanfang zeigt. Mit Shellcode ist da noch nichts, der muss ja erst angesprungen werden ;) .
Für Delta offset kenne ich eigentlich nur

call Delta
Delta:
pop eax <-unsere aktuelle Adresse ist hier
 
Original von CDW
aber in der regel schreibt man die funktion get_sp() in den exploit code
nene, hier ist ein anderer Zusammenhang - und zwar die RET Adresse. Im Code wird diese eben so ermittelt

sag ich doch. mit exploit code mein ich den (meistens c) code der (unter anderem) den shellcode enthaelt. vielleicht raff ich aber auch gerade gar nicht wovon ihr redet. is schon spaet... ;)
 
Original von The Dude
Original von alpha
also für mich waren jetzt deine ersten sätze von großer bedeutung. dann wird also wirklich einfach davon ausgegangen, wenn das eine programm ungefährt an der adresse xy den stack-pointer hat, dann hat ein anderes auf diesem rechner ausgeführte auch ungefähr dieselbe adresse. gut zu wissen :)

so kann mans wohl auch machen, aber in der regel schreibt man die funktion get_sp() in den exploit code und da wird ja dann oft am ende ein exec() syscall gemacht um das zu exploitende program auszufuehren (bei nem lokalen exploit versteht sich).
d.h. das zu exploitende programm wird in den bereich geladen wo vorher das exploitprogramm lief. dadurch hat das zielprogramm genau den stack pointer den der exploit vorher mit get_sp() ermittelt hat.

Also, wenn man sich mal die meisten Exploits auf so Seiten wie milw0rm.org anschaut, dann wird man feststellen, dass dort leider sehr viel mit "hardgecodeten" Addressen gearbeitet wird.

Zu der Frage nach dem Sinn des Code-Beispiel sei mal ein kurzes Zitat erwähnt.

One of the most difficult tasks you face when trying to execute user-supplied shellcode is identifying the startin address of your shellcode. Over the years, many different methods have been contrived to solve this problem. The most popular method was pioneered in the paper "Smashing the Stack for fun and profit". One way to discover the of our shellcode is to guess where the shellcode is in memory. We can made a pretty educated guess, because we know that for every program, the stack begins with the same address. If we know this address, we can attempt to guess how far from this starting address our shellcode is.

Das erklärt doch alles oder?

rushjo
 
noch einmal danke euch allen für die hilfreichen antworten. es ist für mich nun klar, warum es so gemacht wird wie es gemacht wird.

grüße,
alpha.
 
Zurück
Oben