Convertir salida xxd a shellcode


15

Tomar algo de salida de xxd y convertirlo en un código de shell utilizable a mano no es divertido, por lo que su trabajo es automatizar el proceso.

Reglas

Su envío puede ser una función, lambda, script o cualquier equivalente razonable de esos. Puede imprimir el resultado, o si su envío es una función / lambda, también puede devolverlo.

Usted programa debe tomar tres argumentos, el primero en ser una cadena que contiene la salida de xxd, corrió sin argumentos distintos de un nombre de archivo, como esto: xxd some_file. Aquí hay un ejemplo de cómo se verá el primer argumento:

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

Debe tomar esa sección del medio que contiene los bytes (las primeras 8 columnas después de la :) y convertirla en shellcode eliminando cualquier espacio en blanco, luego colocando un \xantes de cada byte.

Esto es lo que debería ser la salida para la entrada anterior (ignorando cualquier otro argumento):

\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

Puede suponer que el primer argumento siempre será una salida xxd válida, ejecutada sin otros argumentos que el nombre del archivo.

Su salida también debe ser una cadena donde las barras diagonales inversas son barras diagonales inversas, no utilizadas como caracteres de escape. Entonces, cuando digo "\ x65", no estoy hablando del byte 0x65, ni siquiera de la letra "A". En código, sería la cadena "\ x65".

El segundo argumento especifica en qué parte de la salida xxd debe comenzar el shellcode, y el tercero especifica dónde debe terminar. Si el tercer argumento es -1, terminará al final de la salida xxd. El segundo y tercer argumento también siempre serán no negativos, excepto cuando el tercero sea-1

Aquí hay algunos casos de prueba:

Argumento 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

Argumento 2: 7Argumento 3: e(ambas son cadenas que representan números hexadecimales)

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

Argumento 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

Argumento 2: 0Argumento 3:2e

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

Argumento 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

Argumento 2: aArgumento 3:-1

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

El código con la menor cantidad de bytes gana. El ganador se anunciará en siete días, el 15 de agosto de 2016 (pero aún se agradecen las presentaciones posteriores).

Actualizar

¡Felicidades a @Adnan por ganar el desafío!


Solo para aclarar, ¿pueden las entradas devolver una cadena o deben imprimirla?
Jordania

Devolver una cadena está bien siempre que sea una función, lambda o algo por el estilo (actualicé las reglas para especificar eso después de que lo haya pedido).
addison

1
¿Podemos también devolver los códigos ASCII normales cuando el código se puede imprimir? Por ejemplo, en ~lugar de \x7e. ¿Y podemos volver en \tlugar de \x09?
orlp

@orlp Lo sentimos, no, debe estar en un formato coherente.
addison

¿Se requiere que los argumentos estén en hexadecimal? Además, la forma en que ha dado el segundo ejemplo, 7parece un índice basado en cero y ees un índice basado en uno ( e-7=7pero hay 8 códigos hexadecimales en su salida), ¿o estoy pasando por alto algo?
Neil

Respuestas:


5

05AB1E , 39 38 bytes

Entrada en el formulario:

arg2
arg3
arg1

Código:

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

Explicación:

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

Utiliza la codificación CP-1252 . Pruébalo en línea! .


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`

Espera el hexdump en STDIN y start / end como argumentos de línea de comandos.

Esto imprime algunas advertencias en STDERR, que está permitido de forma predeterminada.


1
¡Esperaba que alguien realmente lo usara xxden su solución!
addison

@addison Traté de hacerlo, pero mi lang no admite nuevas líneas en la entrada de línea de comandos. : c
Addison Crump

¿Puedo reemplazar 16#con 0x?
Trauma digital

@ DigitalTrauma Pensé que era una xxdcosa, pero parece funcionar en todas partes.
Dennis

1
Sí, bash analiza los números de 0xnestilo hexadecimal y de estilo 0moctal listos para usar : gnu.org/software/bash/manual/bash.html#Shell-Arithmetic . echo $[0x2a] $[052].
Trauma digital

5

JavaScript, 84 bytes

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

Explicación: Elimina todas las partes no deseadas del volcado, antepone \xa cada par hexadecimal y luego extrae la parte deseada del resultado. ||use usa para convertir el cero obtenido al incrementar el -1parámetro en el undefinedque se encuentra un valor mágico que hace sliceque se corte al final de la cadena. 101 bytes si fy tson cadenas de dígitos hexadecimales:

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

En lugar de (s,f,t,u)=>hacerlo s=>f=>t=>u=>, puede guardar algunos bytes.
Ismael Miguel

@IsmaelMiguel Lo sentimos, eso solo funciona para una función con exactamente dos parámetros reales. En mi caso específico, udebe ser un parámetro adicional y no se puede curry.
Neil

@IsmaelMiguel También eso en realidad es más largo ...
Jakob

5

Rubí: 90 89 87 79 63 bytes

-2 bytes gracias a @addison
-8 bytes gracias a @PiersMainwaring

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

Vea las pruebas en repl.it: https://repl.it/Cknc/5


Puede reemplazar .joincon *""para guardar 2 bytes.
addison el

¡Puede reemplazar .map{|h|h.to_i(16)}con .map(&:hex)para ahorrar 8 bytes más!
piersadrian

Gracias @PiersMainwaring! Es tonto de mi parte olvidar eso. ¡Realmente me salvó 16 porque resultó ser más corto recurrir .hexa los argumentos individualmente!
Jordania

4

Jalea , 48 44 bytes

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

Esto espera que el hexdump sea el único argumento de línea de comandos, y los puntos final e inicial en STDIN, en ese orden, separados por un salto de línea.

Pruébalo en línea!


Me encantaría ver una explicación para esto;)
Conor O'Brien

Agregaré uno más tarde, pero primero intentaré jugar al golf. 51 bytes de Jelly vs 69 bytes de Bash no pueden ser correctos ...
Dennis

3

PowerShell v2 +, 175 157 142 133 129 bytes

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

Toma de entrada $a, $b, $c, con $aya sea como una cadena de nueva línea separada por literal, o con el PowerShell `ncarácter que separa las líneas. Establecemos la cadena auxiliar $zcomo la muy procesada de la $asiguiente manera:

Primero, -spliten las líneas nuevas, luego, para cada línea |%{...}, cortamos la sección del medio [10..48], usamos -ne32para eliminar espacios, -joinvolver a unirlos en una cadena larga, -splitcada dos caracteres (manteniendo los dos caracteres) y -ne''eliminar los elementos vacíos. Esto da como resultado una matriz de cadenas de dos elementos, como ('31','c0','b0'...).

Luego cortamos en esa matriz en función de $b fundido con el operador hexadecimal hasta el valor de $c. Necesitamos usar un pseudoternario aquí que explique si $ces -1o no. Si es así, elegimos el .count(es decir, el elemento final) de $z. De lo contrario, simplemente anteponemos el 0xoperador hexadecimal con $cuna cadena. Tenga en cuenta que esto está indexado a cero.

Ese segmento de matriz tiene sus elementos -joined junto con un literal \xpara formar una cadena. Eso se antepone a otro literal \xy el resultado se deja en la tubería. La impresión es implícita.

Ejemplo

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

¿Se puede acceder a shell con este idioma?
Addison Crump

@VTCAKAVSMoACE En teoría, dado el nuevo subsistema de Windows para Linux , debería ser posible conectar cosas y / o pasar parámetros a través de la línea de comandos. La implementación se deja como un ejercicio para el lector. ;-)
AdmBorkBork

2

Gelatina , 39 38 37 bytes

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

Pruébalo en línea!

Ahora supera 05AB1E! (a pesar de la falta de "convertir de hexadecimal" incorporado)

Mismo formato de entrada que la solución de Dennis .

Uso , que es una nueva característica (abreviatura de Ѐ). Sin él, esto tomaría 38 bytes.


Solo funciona para entradas con len hasta 1e9.
user202729

Pero si está en FAT32 (donde el tamaño de entrada es de 2 GB como máximo) es suficiente.
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;

Argumentos dados en la línea de comando como una cadena entre comillas seguida de dos números. Los números se toman en decimal (sé que hexadecimal se usó en los ejemplos pero no se especificó en la publicación)

Técnicamente solo funciona en entradas con hasta 2 ^ 21 bytes ya que el método de subcadena de perl es tonto


Al parecer, el rango es incluido, así por ejemplo 7que edebe dar lugar a una cadena de longitud 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

Divide la cadena original y volca los elementos si tienen menos de cinco caracteres, antepone \xy corta el segundo y el tercer argumento.

Versión de 162 bytes si necesitamos manejar otros tipos de salida no especificados por la pregunta:

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

Esto no funcionará si, por ejemplo, la última línea es algo así, 00000030: 5858 58 XXXya que extraerá la última parte y obtendrá algo así \x58\x58\x58\xXX\xX.
AdmBorkBork

@TimmyD No pensé que ese caso necesitara ser manejado, ignorando las especificaciones del desafío.
atlasólogo

Leí el desafío ya que el primer argumento dado es solo un ejemplo, por lo que podría haber otra xxdsalida utilizada como argumento. "Aquí hay un ejemplo de cómo se verá el primer argumento:"
AdmBorkBork

0

Python 2 y 3 - 164 162 150 146 134 150 bytes

Ahora acepta cadenas hexadecimales para los argumentos segundo y tercero.

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

Sin golf:

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
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.