Konvertiert die xxd-Ausgabe in Shellcode


15

Die Ausgabe von xxd von Hand in verwendbaren Shellcode umzuwandeln, macht keinen Spaß. Ihre Aufgabe ist es, den Prozess zu automatisieren.

Regeln

Ihre Einreichung kann eine Funktion, ein Lambda, ein Skript oder eine sinnvolle Entsprechung davon sein. Sie können das Ergebnis ausdrucken oder, wenn es sich bei Ihrer Einreichung um eine Funktion / Lambda handelt, auch zurücksenden.

Sie programmieren müssen drei Argumente, die erste eine Zeichenfolge ist , um die Ausgabe von xxd, lief ohne Argumente anders als ein Dateiname, wie diese enthalten: xxd some_file. Hier ist ein Beispiel, wie das erste Argument aussehen wird:

00000000: 31c0 b046 31db 31c9 cd80 eb16 5b31 c088  1..F1.1.....[1..
00000010: 4307 895b 0889 430c b00b 8d4b 088d 530c  C..[..C....K..S.
00000020: cd80 e8e5 ffff ff2f 6269 6e2f 7368 4e58  ......./bin/shNX
00000030: 5858 5859 5959 59                        XXXYYYY

Sie müssen diesen mittleren Abschnitt mit den Bytes (die ersten 8 Spalten nach dem :) nehmen und ihn in Shellcode umwandeln, indem Sie Leerzeichen entfernen und dann \xvor jedes Byte ein setzen.

Hier ist, was die Ausgabe für die Eingabe oben sein sollte (andere Argumente ignorieren):

\x31\xc0\xb0\x46\x31\xdb\x31\xc9\xcd\x80\xeb\x16\x5b\x31\xc0\x88\x43\x07\x89\x5b\x08\x89\x43\x0c\xb0\x0b\x8d\x4b\x08\x8d\x53\x0c\xcd\x80\xe8\xe5\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68\x4e\x58\x58\x58\x58\x59\x59\x59\x59

Sie können davon ausgehen, dass das erste Argument immer eine gültige xxd-Ausgabe ist, die ohne andere Argumente als den Dateinamen ausgeführt wird.

Ihre Ausgabe sollte auch eine Zeichenfolge sein, bei der die Backslashes wörtliche Backslashes sind und nicht als Escapezeichen verwendet werden. Wenn ich also "\ x65" sage, spreche ich nicht über das Byte 0x65 oder sogar den Buchstaben "A". Im Code wäre es die Zeichenfolge "\ x65".

Das zweite Argument gibt an, wo in der xxd-Ausgabe der Shellcode beginnen soll, und das dritte gibt an, wo er enden soll. Wenn das dritte Argument lautet -1, endet es am Ende der xxd-Ausgabe. Das zweite und dritte Argument ist auch immer nicht negativ, es sei denn, das dritte ist-1

Hier sind einige Testfälle:

Argument 1:

00000000: 31c0 b046 31db 31c9 cd80 eb16 5b31 c088  1..F1.1.....[1..
00000010: 4307 895b 0889 430c b00b 8d4b 088d 530c  C..[..C....K..S.
00000020: cd80 e8e5 ffff ff2f 6269 6e2f 7368 4e58  ......./bin/shNX
00000030: 5858 5859 5959 59                        XXXYYYY

Argument 2 7:, Argument 3: e(beides Zeichenketten, die Hexadezimalzahlen darstellen)

Ausgabe: \xc9\xcd\x80\xeb\x16\x5b\x31\xc0

Argument 1:

00000000: 31c0 b046 31db 31c9 cd80 eb16 5b31 c088  1..F1.1.....[1..
00000010: 4307 895b 0889 430c b00b 8d4b 088d 530c  C..[..C....K..S.
00000020: cd80 e8e5 ffff ff2f 6269 6e2f 7368 4e58  ......./bin/shNX
00000030: 5858 5859 5959 59                        XXXYYYY

Argument 2 0:, Argument 3:2e

Ausgabe: \x31\xc0\xb0\x46\x31\xdb\x31\xc9\xcd\x80\xeb\x16\x5b\x31\xc0\x88\x43\x07\x89\x5b\x08\x89\x43\x0c\xb0\x0b\x8d\x4b\x08\x8d\x53\x0c\xcd\x80\xe8\xe5\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68\x4e

Argument 1:

00000000: 31c0 b046 31db 31c9 cd80 eb16 5b31 c088  1..F1.1.....[1..
00000010: 4307 895b 0889 430c b00b 8d4b 088d 530c  C..[..C....K..S.
00000020: cd80 e8e5 ffff ff2f 6269 6e2f 7368 4e58  ......./bin/shNX
00000030: 5858 5859 5959 59                        XXXYYYY

Argument 2 a:, Argument 3:-1

Ausgabe: \xeb\x16\x5b\x31\xc0\x88\x43\x07\x89\x5b\x08\x89\x43\x0c\xb0\x0b\x8d\x4b\x08\x8d\x53\x0c\xcd\x80\xe8\xe5\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68\x4e\x58\x58\x58\x58\x59\x59\x59\x59

Der Code mit den wenigsten Bytes gewinnt. Der Gewinner wird in sieben Tagen, am 15. August 2016, bekannt gegeben (Einreichungen danach sind jedoch weiterhin erwünscht).

Aktualisieren

Herzlichen Glückwunsch an @Adnan zum Gewinn der Herausforderung!


Können Einträge zur Verdeutlichung einen String zurückgeben oder müssen sie ihn ausdrucken?
Jordan

Die Rückgabe eines Strings ist in Ordnung, solange es sich um eine Funktion, Lambda oder ähnliches handelt (ich habe die Regeln aktualisiert, um dies anzugeben, nachdem Sie danach gefragt haben).
Addison

1
Können wir die regulären ASCII-Codes auch zurückgeben, wenn der Code druckbar ist? ZB ~statt \x7e. Und können wir \tstattdessen zurückkehren \x09?
Orlp

@orlp Nein, es muss ein konsistentes Format haben.
Addison

Müssen die Argumente hexadezimal sein? Auch die Art und Weise, wie Sie das zweite Beispiel angegeben haben, 7sieht aus wie ein auf Null basierender Index und eist ein auf Eins basierender Index ( e-7=7aber Ihre Ausgabe enthält 8 Hex-Codes), oder überseh ich etwas?
Neil

Antworten:


5

05AB1E , 39 38 Bytes

Eingabe in das Formular:

arg2
arg3
arg1

Code:

²\|vy9F¦}40£ðK}J2ô„\xì²H>²®Qi²}£¹HF¦}J

Erläuterung:

²\                                       # Get the first two inputs and discard them.
  |                                      # Take the rest of the input as an array.
   vy         }                          # For each line...
     9F¦}                                #   Ten times, remove the first character.
         40£                             #   Only remain the substring [0:40].
            ðK                           #   Remove spaces.
               J                         # Join the string.
                2ô                       # Split into pieces of 2.
                  „\xì                   # Prepend a "\x" at each string.
                      ²H                 # Convert the second line from hex to int.
                        >                # Increment by one.
                         ²               # Push the second input again.
                          ®Qi }          # If equal to -1...
                             ²           #   Push the second input again.
                               £         # Take the substring [0:(² + 1)].
                                ¹H       # Convert the first input from hex to int.
                                  F¦}    # Remove that many characters at the beginning.
                                     J   # Join the array and implicitly output.

Verwendet die CP-1252- Codierung. Probieren Sie es online! .


12

Bash + Coreutils + xxd, 73 71 69 Bytes

printf \\x%s `xxd -r|xxd -p -s0x$1 -l$[(e=1+0x$2)?e-0x$1:-1]|fold -2`

Erwartet den Hexdump auf STDIN und start / end als Befehlszeilenargumente.

Dadurch werden einige Warnungen an STDERR ausgegeben, was standardmäßig zulässig ist.


1
Ich hatte gehofft, jemand würde tatsächlich xxdin seiner Lösung verwenden!
Addison

@addison Ich habe es versucht, aber meine Sprache unterstützt keine Zeilenumbrüche in der Kommandozeilen-Eingabe. : c
Addison Crump

Kann ich ersetzen 16#durch 0x?
Digitales Trauma

@DigitalTrauma Ich dachte, es wäre eine xxdSache, aber es scheint überall zu funktionieren.
Dennis

1
Ja, Bash parst 0xnHex- Style- und 0mOktal-Style-Nummern sofort : gnu.org/software/bash/manual/bash.html#Shell-Arithmetic . echo $[0x2a] $[052].
Digital Trauma

5

JavaScript, 84 Bytes

(s,f,t,u)=>s.replace(/.*:|  .*\n?| /g,'').replace(/../g,'\\x$&').slice(f*4,++t*4||u)

Erläuterung: Entfernt alle unerwünschten Teile des Speicherauszugs \x, stellt jedes Hex-Paar voran und extrahiert dann den gewünschten Teil des Ergebnisses. ||uwird verwendet, um die Null zu konvertieren, die durch Inkrementieren des -1Parameters erhalten wird. Hierbei undefinedhandelt es sich um einen magischen Wert, der dazu führt slice, dass das Ende der Zeichenfolge durchschnitten wird. 101 Bytes, wenn fund tZeichenfolgen aus Hexadezimalziffern sind:

(s,f,t,u)=>s.replace(/.*:|  .*\n?| /g,``).replace(/../g,`\\x$&`).slice(`0x${f}`*4,t<0?u:`0x${t}`*4+4)

Stattdessen (s,f,t,u)=>können Sie s=>f=>t=>u=>einige Bytes einsparen.
Ismael Miguel

@IsmaelMiguel Das funktioniert leider nur für eine Funktion mit genau zwei Aktualparametern. In meinem speziellen Fall umuss dies ein zusätzlicher Parameter sein und kann nicht verwendet werden.
Neil

@ IsmaelMiguel Auch das ist eigentlich länger ...
Jakob

5

Ruby: 90 89 87 79 63 Bytes

-2 Bytes dank @addison
-8 Bytes dank @PiersMainwaring

->s,x,y{'\x'+s.scan(/(?<=.{9})\w\w(?=.* )/)[x.hex..y.hex]*'\x'}

Siehe die Tests auf repl.it: https://repl.it/Cknc/5


Sie können ersetzen .joinmit *""zu speichern 2 Byte.
Addison

Sie können ersetzen .map{|h|h.to_i(16)}mit .map(&:hex)8 Bytes mehr zu retten!
Piersadrian

Danke @PiersMainwaring! Dumm von mir, das zu vergessen. Es hat mir tatsächlich 16 erspart, weil es sich als kürzer herausstellte, .hexdie Argumente einzeln aufzurufen !
Jordanien

4

Jelly , 48 44 Bytes

ØhiЀɠ’ḅ¥®L’¤Ạ?⁴‘
ṣ⁷ṫ€⁵ḣ€40Fḟ⁶s©2ḣ¢ṫ¢[“\x”]p

Dies erwartet den Hexdump als einziges Befehlszeilenargument und die End- und Startpunkte auf STDIN in dieser Reihenfolge, getrennt durch einen Zeilenvorschub.

Probieren Sie es online!


Ich würde gerne eine Erklärung dafür sehen;)
Conor O'Brien

Ich werde später eine hinzufügen, aber ich werde versuchen, es zuerst ein bisschen Golf zu spielen. 51 Bytes Jelly vs 69 Bytes Bash können nicht richtig sein ...
Dennis

3

PowerShell v2 +, 175 157 142 133 129 Byte

param($a,$b,$c)'\x'+(($z=$a-split"`n"|%{$_[10..48]-ne32-join''-split'(..)'-ne''})["0x$b"..(("0x$c",$z.count)[$c-eq-1])]-join'\x')

Nimmt die Eingabe $a, $b, $c, mit $aentweder als eine Neuen - Zeile - Literal-Zeichenkette getrennt oder mit dem Power `nCharakter die Linien trennen. Wir setzen den Helferstring wie folgt $zstark bearbeitet $a:

Zuerst haben wir -splitauf neue Zeilen, dann für jede Zeile |%{...}, in Scheiben schneiden wir den mittleren Abschnitt [10..48], verwenden Sie die -ne32Räume zu entfernen, -joinsie wieder zusammen in einer langen Reihe, -splites auf je zwei Zeichen (wobei die beiden Zeichen) und -ne''die leeren Elemente zu entfernen. Dies führt zu einem Array von Zeichenfolgen mit zwei Elementen, wie z ('31','c0','b0'...).

Wir schneiden dann in dieses Array, basierend auf der $bUmwandlung mit dem hexadezimalen Operator bis zum Wert von $c. Wir müssen hier einen Pseudoternären verwenden, der erklärt, ob dies der Fall $cist -1oder nicht. Wenn ja, wählen wir das .count(dh das Endelement) von $z. Ansonsten stellen wir dem 0xhexadezimalen Operator nur $ceine Zeichenfolge voran . Beachten Sie, dass dies nullindiziert ist.

Die Elemente dieses Array-Slice werden -joinmit einem Literal \xzu einer Zeichenfolge zusammengefasst. Dem steht ein weiteres Literal voran, \xund das Ergebnis wird in der Pipeline belassen. Drucken ist implizit.

Beispiel

PS C:\Tools\Scripts\golfing> .\xxd-output.ps1 "00000000: 31c0 b046 31db 31c9 cd80 eb16 5b31 c088  1..F1.1.....[1..
00000010: 4307 895b 0889 430c b00b 8d4b 088d 530c  C..[..C....K..S.
00000020: cd80 e8e5 ffff ff2f 6269 6e2f 7368 4e58  ......./bin/shNX
00000030: 5858 5859 5959 59                        XXXYYYY" a -1
\xeb\x16\x5b\x31\xc0\x88\x43\x07\x89\x5b\x08\x89\x43\x0c\xb0\x0b\x8d\x4b\x08\x8d\x53\x0c\xcd\x80\xe8\xe5\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68\x4e\x58\x58\x58\x58\x59\x59\x59\x59

Können Sie mit dieser Sprache auf die Shell zugreifen?
Addison Crump

@VTCAKAVSMoACE In Anbetracht des neuen Windows-Subsystems für Linux sollte es theoretisch möglich sein, Dinge zusammenzufassen und / oder Parameter über die Befehlszeile zu übergeben. Die Implementierung bleibt dem Leser als Übung überlassen. ;-)
AdmBorkBork

2

Jelly , 39 38 37 Bytes

ØhiⱮɠ’ḅ¥ȷ9Ṃ?⁴‘
Ỵṫ€⁵ḣ€40Fḟ⁶s2ṭ€⁾\xḣ¢ṫ¢

Probieren Sie es online!

Jetzt schlägt 05AB1E! (trotz fehlender "hexadezimaler Konvertierung" eingebaut)

Gleiches Eingabeformat wie die Lösung von Dennis .

Verwenden Sie , was eine neue Funktion ist (Abkürzung für Ѐ). Ohne dies würde dies 38 Bytes dauern.


Funktioniert nur für Eingaben mit len ​​bis 1e9.
user202729

Wenn es sich jedoch um FAT32 handelt (wobei die Eingabegröße höchstens 2 GB beträgt), reicht es aus.
user202729

1

Perl, 114 Bytes

($_,$a,$b)=@ARGV;s/^.*:|\S*$|\s//gm;@_=(m/../g);for(@_){s/^/\\x/}$"='';say substr"@_",4*$a,$b!=-1?4*($a+$b):2<<20;

Argumente, die in der Befehlszeile in Anführungszeichen gefolgt von zwei Zahlen angegeben werden. Die Zahlen sind dezimal (ich weiß, hex wurde in den Beispielen verwendet, aber es wurde nicht in der Post angegeben)

Funktioniert technisch nur bei Eingaben mit bis zu 2 ^ 21 Bytes, da Perls Teilstring-Methode albern ist


Offenbar ist der Bereich , einschließlich, so zum Beispiel 7an ein einer Reihe von Länge zur Folge haben sollte 32
Neil

1

Python, 140 Bytes

lambda O,a,b:''.join(sum([['\\x'+x[:2],('','\\x')[len(x)>2]+x[2:]]for x in O.split()if len(x)<5],[])[int(a,16):(int(b,16)+1,None)[b=='-1']])

https://repl.it/ClB3

Teilt die ursprüngliche Zeichenfolge auf und gibt die Elemente aus, wenn sie weniger als fünf Zeichen haben, voranstehen \xund durch das zweite und dritte Argument getrennt werden.

162-Byte-Version, wenn wir andere Ausgabetypen verarbeiten müssen, die in der Frage nicht angegeben sind:

import re
J=''.join
def f(x,a,b):r=J(J(re.findall(':(.*?)  ',x)).split());print J(['\\x'+i+j for i,j in zip(r,r[1:])][::2][int(a,16):(int(b,16)+1,None)[b=='-1']])

Dies funktioniert nicht, wenn z. B. die letzte Zeile ungefähr so ​​ist, 00000030: 5858 58 XXXda sie den letzten Teil herauszieht und Sie ungefähr so ​​etwas erhalten \x58\x58\x58\xXX\xX.
AdmBorkBork

@TimmyD Ich habe nicht gedacht, dass dieser Fall bearbeitet werden muss, da er die Vorgaben der Herausforderung nicht erfüllt.
Atlasologe

Ich habe die Herausforderung gelesen, da das erste Argument nur ein Beispiel ist, sodass xxdstattdessen auch eine andere Ausgabe als Argument verwendet werden kann. "Hier ist ein Beispiel, wie das erste Argument aussehen wird:"
AdmBorkBork

0

Python 2 und 3 - 164 162 150 146 134 150 Bytes

Akzeptiert jetzt hexadezimale Zeichenfolgen für das zweite und dritte Argument.

j=''.join
def f(a,b,c):s=j(x[10:49].replace(' ','')for x in a.split('\n'));print(j('\\x'+s[i:i+2]for i in range(int(b,16)*2,1+2*int(c,16)%len(s),2))

0

Python 3.5, 125 Bytes

import re
lambda s,b,e:re.sub(r'(\w\w)',r'\\x\1',re.sub(r'^.*?:|  .*$|\s','',s,0,8)[2*int(b,16):[2*int(e,16)+2,None][e<'0']])

Ungolfed:

def f(s,b,e):
    b = 2*int(b,16)
    e = [2*int(e,16)+2,None][e<'0']
    x = re.sub(r'''(?v)   # verbose (not in golfed version)
            ^.*?:     # match begining of line to the ':'
           |  .*$     # or match '  ' to end of line
           |\s        # or match whitespace
           ''',
           '',        # replacement
           s,
           0,         # replace all matches 
           re.M       # multiline mode
           )
    y = re.sub(r'(\w\w)', # match pairs of 'word' characters
           r'\\x\1',  # insert \x
            x[b:e])
    return y
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.