Converti l'output xxd in shellcode


15

Prendere un po 'di output da xxd e trasformarlo a mano in shellcode utilizzabile non è divertente, quindi il tuo compito è automatizzare il processo.

Regole

L'invio può essere una funzione, lambda, script o qualsiasi equivalente ragionevole di quelli. È possibile stampare il risultato o se l'invio è una funzione / lambda, è possibile anche restituirlo.

È il programma deve prendere tre argomenti, il primo è una stringa contenente l'output di xxd, corse senza argomenti diversi da un nome di file, come questo: xxd some_file. Ecco un esempio di come apparirà il primo argomento:

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

Devi prendere quella sezione centrale contenente i byte (le prime 8 colonne dopo la :) e trasformarla in shellcode rimuovendo qualsiasi spazio bianco, quindi inserendo un \xprima di ogni byte.

Ecco come dovrebbe essere l'output per l'input sopra (ignorando qualsiasi altro argomento):

\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

Puoi presumere che il primo argomento sarà sempre un output xxd valido, eseguito senza argomenti diversi dal nome file.

L'output dovrebbe anche essere una stringa in cui le barre rovesciate sono letterali barre rovesciate, non utilizzate come caratteri di escape. Quindi quando dico "\ x65", non sto parlando del byte 0x65, o anche della lettera "A". Nel codice, sarebbe la stringa "\ x65".

Il secondo argomento specifica dove dovrebbe iniziare lo shellcode nell'output xxd, mentre il terzo specifica dove dovrebbe finire. Se il terzo argomento è -1, terminerà alla fine dell'output xxd. Anche il secondo e il terzo argomento saranno sempre non negativi, tranne quando lo è il terzo-1

Ecco alcuni casi di test:

Argomento 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

Argomento 2:, 7Argomento 3: e(queste sono entrambe stringhe che rappresentano numeri esadecimali)

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

Argomento 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

Argomento 2:, 0Argomento 3:2e

Produzione: \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

Argomento 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

Argomento 2:, aArgomento 3:-1

Produzione: \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

Vince il codice con il minor numero di byte. Il vincitore sarà annunciato tra sette giorni, il 15 agosto 2016 (ma le iscrizioni successive saranno ancora apprezzate).

Aggiornare

Congratulazioni a @Adnan per aver vinto la sfida!


Solo per chiarire, le voci possono restituire una stringa o devono stamparla?
Giordania,

Restituire una stringa va bene purché sia ​​una funzione, lambda o qualcosa del genere (ho aggiornato le regole per specificarlo dopo averlo chiesto).
addison

1
Possiamo anche restituire i normali codici ASCII quando il codice è stampabile? Ad esempio ~invece di \x7e. E possiamo tornare \tinvece di \x09?
orlp

@orlp Siamo spiacenti, deve essere in un formato coerente.
addison

Gli argomenti devono essere in esadecimale? Inoltre, il modo in cui hai dato il secondo esempio, 7sembra un indice a base zero ed eè un indice a base singola ( e-7=7ma ci sono 8 codici esadecimali nel tuo output) o sto trascurando qualcosa?
Neil,

Risposte:


5

05AB1E , 39 38 byte

Inserisci nel modulo:

arg2
arg3
arg1

Codice:

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

Spiegazione:

²\                                       # 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.

Utilizza la codifica CP-1252 . Provalo online! .


12

Bash + coreutils + xxd, 73 71 69 byte

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

Prevede il hexdump su STDIN e inizia / termina come argomenti della riga di comando.

Questo stampa alcuni avvisi a STDERR, che è consentito per impostazione predefinita.


1
Speravo che qualcuno avrebbe effettivamente usato xxdnella loro soluzione!
addison

@addison Ho provato a farlo, ma la mia lingua non supporta le nuove righe nell'input da riga di comando. : c
Addison Crump

Sono in grado di sostituire 16#con 0x?
Trauma digitale

@DigitalTrauma Ho pensato che fosse una xxdcosa, ma sembra funzionare ovunque.
Dennis,

1
Sì, bash analizza immediatamente i numeri di 0xnstile esadecimale e 0mottale: gnu.org/software/bash/manual/bash.html#Shell-Arithmetic . echo $[0x2a] $[052].
Trauma digitale

5

JavaScript, 84 byte

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

Spiegazione: rimuove tutte le parti indesiderate del dump, antepone \xa ciascuna coppia esadecimale, quindi estrae la parte desiderata del risultato. ||uviene utilizzato per convertire lo zero ottenuto incrementando il -1parametro in undefinedcui è un valore magico che provoca il slicetaglio alla fine della stringa. 101 byte se fe tsono stringhe di cifre esadecimali:

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

Invece di (s,f,t,u)=>, puoi fare s=>f=>t=>u=>, per salvare qualche byte.
Ismael Miguel,

@IsmaelMiguel Siamo spiacenti, funziona solo con una funzione con esattamente due parametri effettivi. Nel mio caso specifico, udeve essere un parametro aggiuntivo e non può essere elaborato.
Neil,

@IsmaelMiguel Anche questo è in realtà più lungo ...
Jakob,

5

Rubino: 90 89 87 79 63 byte

-2 byte grazie a @addison
-8 byte grazie a @PiersMainwaring

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

Vedi i test su repl.it: https://repl.it/Cknc/5


È possibile sostituire .joincon *""per salvare 2 byte.
addison

È possibile sostituire .map{|h|h.to_i(16)}con .map(&:hex)per salvare altri 8 byte!
piersadrian,

Grazie @PiersMainwaring! Sciocco da parte mia dimenticarlo. In realtà mi ha salvato 16 perché si è rivelato più breve invocare .hexgli argomenti individualmente!
Giordania,

4

Gelatina , 48 44 byte

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

Ciò prevede che hexdump sia l'unico argomento della riga di comando e i punti di fine e inizio su STDIN, in quell'ordine, separati da un avanzamento di riga.

Provalo online!


Mi piacerebbe vedere una spiegazione per questo;)
Conor O'Brien il

Ne aggiungerò uno più tardi, ma proverò a giocarci un po 'prima. 51 byte di Jelly contro 69 byte di Bash non possono avere ragione ...
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')

Prende ingresso $a, $b, $c, con $acome una stringa nuova riga separata letterale, o con l'PowerShell `ncarattere che separa le linee. Impostiamo la stringa di supporto $zcome elaborata pesantemente $acome segue:

Prima di tutto -splitsu newline, quindi, per ogni riga |%{...}, suddividiamo la sezione centrale [10..48], utilizziamo -ne32per rimuovere gli spazi, -joinrimettendoli insieme in una lunga stringa, -splitsu ogni due caratteri (mantenendo i due caratteri) e -ne''per rimuovere gli elementi vuoti. Ciò si traduce in una matrice di stringhe a due elementi, come ('31','c0','b0'...).

Quindi suddividiamo in quell'array in base al $bcast con l'operatore esadecimale fino al valore di $c. Abbiamo bisogno di usare uno pseudo-ternario che spieghi se lo $cè -1o no. Se lo è, scegliamo .count(cioè l'elemento finale) di $z. Altrimenti, basta anteporre l' 0xoperatore esadecimale con $cuna stringa. Si noti che questo è a zero.

Quella porzione di matrice ha i suoi elementi -joined insieme con un valore letterale \xper formare una stringa. Questo è anteposto con un altro letterale \xe il risultato viene lasciato sulla pipeline. La stampa è implicita.

Esempio

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

Puoi accedere alla shell con questa lingua?
Addison Crump

@VTCAKAVSMoACE In teoria, dato il nuovo sottosistema Windows per Linux , dovrebbe essere possibile raggruppare le cose e / o passare parametri tramite riga di comando. L'implementazione è lasciata come esercizio per il lettore. ;-)
AdmBorkBork

2

Gelatina , 39 38 37 byte

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

Provalo online!

Ora batte 05AB1E! (nonostante la mancanza di built-in "converti da esadecimale")

Stesso formato di input della soluzione di Dennis .

Usa , che è una nuova funzionalità (abbreviazione di Ѐ). Senza di essa, ciò richiederebbe 38 byte.


Funziona solo con input con len fino a 1e9.
user202729

Ma se è su FAT32 (dove la dimensione di input è al massimo di 2 GB) è sufficiente.
user202729

1

Perl, 114 byte

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

Argomenti forniti sulla riga di comando come una stringa tra virgolette seguita da due numeri. I numeri sono presi in decimale (so che hex è stato usato negli esempi ma non è stato specificato nel post)

Tecnicamente funziona solo su input con un massimo di 2 ^ 21 byte poiché il metodo di sottostringa di perl è sciocco


A quanto pare il range è compreso, così per esempio 7a edovrebbe tradursi in una stringa di lunghezza 32.
Neil

1

Python, 140 byte

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

Divide la stringa originale e scarica gli elementi se sono meno di cinque caratteri, antepone \xe sezioni per il secondo e il terzo argomento.

Versione a 162 byte se dobbiamo gestire altri tipi di output non specificati dalla domanda:

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']])

Questo non funzionerà se, ad esempio, l'ultima riga è qualcosa di simile 00000030: 5858 58 XXXpoiché estrarrà l'ultima porzione e otterrai qualcosa di simile \x58\x58\x58\xXX\xX.
AdmBorkBork,

@TimmyD Non pensavo che quel caso dovesse essere gestito, andando oltre le specifiche della sfida.
atlanteologo

Ho letto la sfida poiché il primo argomento dato è solo un esempio, quindi potrebbe esserci invece un altro xxdoutput usato come argomento. "Ecco un esempio di come sarà il primo argomento:"
AdmBorkBork,

0

Python 2 e 3 - 164 162 150 146 134 150 byte

Ora accetta stringhe esadecimali per il secondo e il terzo argomento.

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 byte

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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.