2016-06-24 15 views
1

Grundsätzlich verwende ich ptrace, um einen Shell-Code zu einem Remote-Prozess zur Ausführung zu injizieren. Aber ich habe ein seltsames Verhalten bezüglich des RIP-Registers gefunden.seltsame Verhaltenseinstellung RIP mit ptrace

Was ich tue ist, ich kopiere meinen Shell-Code an die Startadresse, wo das Programm zugeordnet ist. Dann setze ich den RIP mit ptrace auf die Adresse, wo die Startadresse ist. Und dann setze ich den Zielprozess zur Ausführung des Codes fort. Sobald der Shell-Code beendet ist (indem int3 ausgeführt wird), erhalte ich ein Signal und stelle den Code wieder her, den ich gerade geändert habe.

Es funktioniert gut, außer wenn der Remote-Prozess ist blockiert innerhalb eines Systemaufrufs wie sleep. Wenn der Remote-Prozess innerhalb eines Systemaufrufs in dem Moment blockiert wird, in dem ich den Prozess anhefte, nachdem ich den RIP auf den Ort gesetzt habe, an dem ich meinen Shell-Code ausführen möchte, und dann den Zielprozess wieder aktiviere, werde ich feststellen, dass der RIP tatsächlich 2 weniger ist als die Adresse, die ich in den Ptrace-Anruf eingegeben habe. Wenn ich zum Beispiel den RIP auf 0x4000 setze, wird der RIP nach dem Fortsetzen 0x3ffe. Normalerweise stürzt es wegen des Segmentfehlers für meinen Fall ab. Aber wenn ich das Register gleich nachdem ich es eingestellt habe, ohne den Prozess wieder aufzunehmen, ist der RIP der Wert, den ich gerade gesetzt habe. Momentan arbeite ich daran, indem ich 2 nop-Anweisungen vor meinen Shell-Code einfüge und immer 2 hinzufüge, wenn ich den RIP einstelle. Ich will nur wissen, gibt es etwas, das ich vermisse, um den RIP zu setzen, oder meine ganze Methode, Code zu injizieren, ist total instabil?

Meine Dev-Box ist Ubuntu14.04, Kernel ist 3.13.0-45-generisch.

Antwort

2

Wenn ich mich richtig erinnere, wenn Sie den Prozess unterbrechen, während es in einem Syscall blockiert ist, wird der Wert des Programmzählers beim Fortsetzen von sizecf (syscall Anweisung) vom Kernel subtrahiert. Sobald Sie also PTRACE_DETACH ausgeführt haben, wird der Prozess den Syscall erneut ausführen, von dem es unterbrochen wurde.

Ich überwinde das Problem auf die gleiche Weise wie du es getan hast (immer einen kleinen NOP-Schlitten hinzufügend und RIP inkrementierend).

+0

Können Sie etwas darüber erklären, warum der Kernel die Größe von syscall subtrahieren muss, wenn er den Anruf fortsetzt? Vielen Dank ! – dianpeng

+0

Ich nehme an, es ist Teil der RESTART-Behandlung. Sie stoppen es, indem Sie ihm ein Signal senden. Wenn der Kernel den Syscall nach Beendigung des Signal-Handlers neu starten möchte, muss er in den Kernel zurückkehren. Dazu müssen Sie sicherstellen, dass Sie die Anweisung "syscall" erneut ausführen. –