Converter saída xxd em shellcode


15

Tomar alguma saída do xxd e transformá-lo em código de shell utilizável manualmente não é divertido, portanto, seu trabalho é automatizar o processo.

Regras

Seu envio pode ser uma função, lambda, script ou qualquer equivalente razoável deles. Você pode imprimir o resultado ou, se o seu envio for uma função / lambda, também poderá devolvê-lo.

Você programa deverá ter três argumentos, o primeiro sendo uma string contendo a saída de xxd, correu com nenhum outro do que um nome de arquivo argumentos, como este: xxd some_file. Aqui está um exemplo de como será o primeiro 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

Você precisa pegar a seção do meio que contém os bytes (as 8 primeiras colunas após a :) e transformá-la em código de shell removendo qualquer espaço em branco e colocando um \xantes de cada byte.

Aqui está o que a saída deve ser para a entrada acima (ignorando quaisquer outros argumentos):

\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

Você pode assumir que o primeiro argumento sempre será uma saída xxd válida, executada sem nenhum argumento além do nome do arquivo.

Sua saída também deve ser uma sequência em que as barras invertidas são barras invertidas literais, não usadas como caracteres de escape. Então, quando digo "\ x65", não estou falando do byte 0x65 ou mesmo da letra "A". No código, seria a string "\ x65".

O segundo argumento especifica onde na saída xxd o código do shell deve iniciar e o terceiro especifica onde deve terminar. Se o terceiro argumento for -1, ele terminará no final da saída xxd. O segundo e o terceiro argumento também sempre serão não negativos, exceto quando o terceiro for-1

Aqui estão alguns casos de teste:

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 são cadeias que representam números hexadecimais)

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

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

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

O código com menos bytes vence. O vencedor será anunciado em sete dias, em 15 de agosto de 2016 (mas as inscrições depois disso ainda serão apreciadas).

Atualizar

Parabéns a @Adnan por vencer o desafio!


Apenas para esclarecer, as entradas podem retornar uma sequência ou devem imprimi-la?
Jordânia

Retornar uma string é bom, desde que seja uma função, lambda ou algo parecido (atualizei as regras para especificar isso depois que você perguntou).
21416

1
Também podemos retornar os códigos ASCII regulares quando o código estiver imprimível? Por exemplo, em ~vez de \x7e. E podemos voltar em \tvez de \x09?
orlp 8/08/16

@orlp Desculpe, não, ele precisa estar em um formato consistente.
21416

Os argumentos devem estar em hexadecimal? Além disso, da maneira que você deu o segundo exemplo, 7parece um índice baseado em zero e eé um índice baseado em um ( e-7=7mas há 8 códigos hexadecimais em sua saída), ou estou ignorando alguma coisa?
Neil

Respostas:


5

05AB1E , 39 38 bytes

Entrada no formulário:

arg2
arg3
arg1

Código:

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

Explicação:

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

Usa a codificação CP-1252 . Experimente 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`

Espera o hexdump no STDIN e inicia / termina como argumentos da linha de comando.

Isso imprime alguns avisos ao STDERR, que é permitido por padrão.


1
Eu esperava que alguém realmente usasse xxdsua solução!
21416

@addison Eu tentei, mas meu idioma não suporta novas linhas na entrada da linha de comando. : c
Addison Crump

Eu posso substituir 16#por 0x?
Digital Trauma

@DigitalTrauma Eu pensei que era uma xxdcoisa, mas parece funcionar em todos os lugares.
Dennis

1
Sim, o bash analisa os números de estilo 0xnhexadecimal e de 0mestilo octal imediatamente : 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)

Explicação: Remove todas as partes indesejadas do dump, precede \xcada par hexadecimal e extrai a parte desejada do resultado. ||ué usado para converter o zero obtido incrementando o -1parâmetro no undefinedqual é um valor mágico que faz slicecom que a fatia seja finalizada no final da string. 101 bytes se fe tsão cadeias de dígitos hexadecimais:

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

Em vez de (s,f,t,u)=>, você pode fazer s=>f=>t=>u=>, salvar alguns bytes.
Ismael Miguel

@IsmaelMiguel Desculpe, isso só funciona para uma função com exatamente dois parâmetros reais. No meu caso específico, udeve ser um parâmetro adicional e não pode ser curry.
Neil

@IsmaelMiguel também que na verdade é mais ...
Jakob

5

Ruby: 90 89 87 79 63 bytes

-2 bytes graças a @addison
-8 bytes graças a @PiersMainwaring

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

Veja os testes em repl.it: https://repl.it/Cknc/5


Você pode substituir .joinpor *""para salvar 2 bytes.
21416 addison

Você pode substituir .map{|h|h.to_i(16)}por .map(&:hex)para economizar mais 8 bytes!
piersadrian 9/08/16

Obrigado @PiersMainwaring! Bobo da minha parte esquecer isso. Na verdade, me salvou 16, porque acabou sendo mais curto invocar .hexos argumentos individualmente!
Jordânia

4

Geléia , 48 44 bytes

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

Isso espera o hexdump como único argumento da linha de comando e os pontos final e inicial no STDIN, nessa ordem, separados por um avanço de linha.

Experimente online!


Eu adoraria ver uma explicação para isso;)
Conor O'Brien

Vou adicionar um mais tarde, mas vou tentar jogar um pouco primeiro. 51 bytes de Jelly vs 69 bytes de Bash não pode estar certo ...
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 entrada $a, $b, $c, com $atanto como uma corda separada por nova linha literal, ou com o PowerShell `ncarácter separando as linhas. Definimos a sequência auxiliar $zcomo o altamente processado da $aseguinte maneira:

Primeiro, -splitem novas linhas, em seguida, para cada linha |%{...}, dividimos a seção do meio [10..48], usamos a -ne32para remover espaços, -joinjuntando-a novamente em uma cadeia longa, -splitem cada dois caracteres (mantendo os dois caracteres) e -ne''para remover os elementos vazios. Isso resulta em uma matriz de cadeias de dois elementos, como ('31','c0','b0'...).

Em seguida, dividimos o array com base no $belenco com o operador hexadecimal até o valor de $c. Precisamos usar um pseudo-ternário aqui que explique se $cé -1ou não. Se for, escolhemos o .count(ou seja, o elemento final) de $z. Caso contrário, apenas adicionamos o 0xoperador hexadecimal $cem uma string. Observe que isso é indexado a zero.

Essa fatia da matriz tem seus elementos -joineditados junto com um literal \xpara formar uma sequência. Isso é anexado a outro literal \xe o resultado é deixado no pipeline. A impressão está implícita.

Exemplo

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

Você pode acessar o shell com esse idioma?
Addison Crump

@VTCAKAVSMoACE Em teoria, dado o novo Windows Subsystem para Linux , deve ser possível canalizar as coisas e / ou passar parâmetros via linha de comando. A implementação é deixada como um exercício para o leitor. ;-)
AdmBorkBork 08/08

2

Geléia , 39 38 37 bytes

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

Experimente online!

Agora supera 05AB1E! (apesar da falta de "converter de hexadecimal" embutido)

Mesmo formato de entrada que a solução de Dennis .

Use , que é um novo recurso (abreviação de Ѐ). Sem ele, isso levaria 38 bytes.


Funciona apenas para entrada com len até 1e9.
user202729

Mas se estiver no FAT32 (onde o tamanho da entrada é de no máximo 2 GB) é 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 na linha de comando como uma string entre aspas seguida por dois números. Os números são tirados em decimal (eu sei que hex foi usado nos exemplos, mas não foi especificado no post)

Tecnicamente, funciona apenas em entradas com até 2 ^ 21 bytes, já que o método de substring do perl é tolo


Aparentemente, o intervalo é inclusivo, assim, por exemplo 7a edeve resultar em uma cadeia de comprimento 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 a string original e despeja os elementos se tiverem menos de cinco caracteres, acrescenta \x e fatias pelo segundo e terceiro argumentos.

Versão de 162 bytes, se precisarmos lidar com outros tipos de saída não especificados pela pergunta:

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

Isso não funcionará se, por exemplo, a última linha for algo como, 00000030: 5858 58 XXXuma vez que puxará a última parte e você obterá algo como \x58\x58\x58\xXX\xX.
AdmBorkBork

@ TimmyD Eu não acho que esse caso precise ser resolvido, saindo das especificações do desafio.
Atlasologist

Eu li o desafio, já que o primeiro argumento fornecido é apenas um exemplo; portanto, poderia haver outra xxdsaída usada como argumento. "Aqui está um exemplo de como será o primeiro argumento:"
AdmBorkBork

0

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

Agora aceita cadeias hexadecimais para o segundo e o terceiro argumentos.

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
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.