Convertir la sortie xxd en shellcode

15

Prendre un peu de sortie de xxd et le transformer à la main en shellcode utilisable n'est pas amusant, donc votre travail consiste à automatiser le processus.

Règles

Votre soumission peut être une fonction, un lambda, un script ou tout équivalent raisonnable de ceux-ci. Vous pouvez imprimer le résultat, ou si votre soumission est une fonction / lambda, vous pouvez également la renvoyer.

Vous devez programme prendre trois arguments, la première étant une chaîne contenant la sortie de xxd, RAN sans argument autre qu'un nom de fichier, comme ceci: xxd some_file. Voici un exemple de ce à quoi ressemblera le premier argument:

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

Vous devez prendre cette section du milieu contenant les octets (les 8 premières colonnes après le :) et le transformer en shellcode en supprimant les espaces, puis en mettant un \xavant chaque octet.

Voici ce que la sortie devrait être pour l'entrée ci-dessus (en ignorant tout autre argument):

\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

Vous pouvez supposer que le premier argument sera toujours une sortie xxd valide, exécutée sans autre argument que le nom de fichier.

Votre sortie doit également être une chaîne où les barres obliques inverses sont des barres obliques inverses littérales, non utilisées comme caractères d'échappement. Donc quand je dis "\ x65", je ne parle pas de l'octet 0x65, ni même de la lettre "A". Dans le code, ce serait la chaîne "\ x65".

Le deuxième argument spécifie où dans la sortie xxd le shellcode doit commencer et le troisième spécifie où il doit se terminer. Si le troisième argument est -1, il se terminera à la fin de la sortie xxd. Les deuxième et troisième arguments seront également toujours non négatifs, sauf lorsque le troisième est-1

Voici quelques cas de test:

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:, 7Argument 3: e(ce sont les deux chaînes représentant des nombres hexadécimaux)

Production: \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:, 0Argument 3:2e

Production: \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:, aArgument 3:-1

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

Le code avec le moins d'octets gagne. Le gagnant sera annoncé dans sept jours, le 15 août 2016 (mais les candidatures après cette date sont toujours appréciées).

Mise à jour

Félicitations à @Adnan pour avoir remporté le défi!

addison
la source
Juste pour clarifier, les entrées peuvent-elles retourner une chaîne ou doivent-elles l'imprimer?
Jordan
Renvoyer une chaîne est très bien tant qu'il s'agit d'une fonction, lambda, ou quelque chose comme ça (j'ai mis à jour les règles pour spécifier cela après avoir demandé).
addison
1
Pouvons-nous également retourner les codes ASCII normaux lorsque le code est imprimable? Par exemple ~au lieu de \x7e. Et pouvons-nous revenir \tau lieu de \x09?
orlp
@orlp Désolé non, il doit être dans un format cohérent.
addison
Les arguments doivent-ils être en hexadécimal? De plus, la façon dont vous avez donné le deuxième exemple 7ressemble à un index à base zéro et à eun index à base unique ( e-7=7mais il y a 8 codes hexadécimaux dans votre sortie), ou suis-je en train d'oublier quelque chose?
Neil

Réponses:

5

05AB1E , 39 38 octets

Saisie sous forme:

arg2
arg3
arg1

Code:

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

Explication:

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

Utilise l' encodage CP-1252 . Essayez-le en ligne! .

Adnan
la source
12

Bash + coreutils + xxd, 73 71 69 octets

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

Attend l'hexdump sur STDIN et start / end comme arguments de ligne de commande.

Cela affiche certains avertissements dans STDERR, ce qui est autorisé par défaut.

Dennis
la source
1
J'espérais que quelqu'un utiliserait réellement xxdsa solution!
addison
@addison J'ai essayé, mais ma langue ne prend pas en charge les sauts de ligne en entrée de ligne de commande. : c
Addison Crump
Je peux remplacer 16#par 0x?
Digital Trauma du
@DigitalTrauma Je pensais que c'était une xxdchose, mais cela semble fonctionner partout.
Dennis
1
Oui, bash analyse les numéros de 0xnstyle hexadécimal et 0moctal hors de la boîte: gnu.org/software/bash/manual/bash.html#Shell-Arithmetic . echo $[0x2a] $[052].
Digital Trauma
5

JavaScript, 84 octets

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

Explication: supprime toutes les parties indésirables du vidage, ajoute \xà chaque paire hexadécimale, puis extrait la partie souhaitée du résultat. ||uest utilisé pour convertir le zéro obtenu en incrémentant le -1paramètre dans undefinedlequel est une valeur magique qui provoque slicele découpage à la fin de la chaîne. 101 octets si fet tsont des chaînes de chiffres hexadécimaux:

(s,f,t,u)=>s.replace(/.*:|  .*\n?| /g,``).replace(/../g,`\\x$&`).slice(`0x${f}`*4,t<0?u:`0x${t}`*4+4)
Neil
la source
Au lieu de (s,f,t,u)=>, vous pouvez le faire s=>f=>t=>u=>pour économiser quelques octets.
Ismael Miguel
@IsmaelMiguel Désolé, cela ne fonctionne que pour une fonction avec exactement deux paramètres réels. Dans mon cas spécifique, le udoit être un paramètre supplémentaire et ne peut pas être curry.
Neil
@IsmaelMiguel C'est aussi en fait plus long ...
Jakob
5

Rubis: 90 89 87 79 63 octets

-2 octets grâce à @addison
-8 octets grâce à @PiersMainwaring

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

Voir les tests sur repl.it: https://repl.it/Cknc/5

Jordan
la source
Vous pouvez remplacer .joinpar *""pour économiser 2 octets.
addison
Vous pouvez remplacer .map{|h|h.to_i(16)}par .map(&:hex)pour économiser 8 octets supplémentaires!
piersadrian
Merci @PiersMainwaring! Idiot de ma part d'oublier ça. Cela m'a en fait sauvé 16 car il s'est avéré plus court d'appeler .hexles arguments individuellement!
Jordan
4

Gelée , 48 44 octets

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

Cela attend l'hexdump comme unique argument de ligne de commande, et les points de fin et de début sur STDIN, dans cet ordre, séparés par un saut de ligne.

Essayez-le en ligne!

Dennis
la source
J'aimerais voir une explication à cela;)
Conor O'Brien
J'en ajouterai un plus tard, mais j'essaierai d'abord de jouer au golf. 51 octets de Jelly vs 69 octets de Bash ne peuvent pas avoir raison ...
Dennis
3

PowerShell v2 +, 175 157 142 133 129 octets

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

Prend entrée $a, $b, $c, avec $acomme étant soit un littéral chaîne séparée saut de ligne ou avec le PowerShell `ncaractère séparant les lignes. Nous définissons la chaîne d'aide $zcomme fortement traitée $acomme suit -

Nous -splitcommençons d' abord par des sauts de ligne, puis, pour chaque ligne |%{...}, nous coupons la section du milieu [10..48], utilisons le -ne32pour supprimer les espaces, -joinle remettons ensemble en une longue chaîne, -splitsur tous les deux caractères (en gardant les deux caractères) et -ne''pour supprimer les éléments vides. Il en résulte un tableau de chaînes à deux éléments, comme ('31','c0','b0'...).

Nous découpons ensuite ce tableau en fonction de la $bconversion avec l'opérateur hexadécimal jusqu'à la valeur de $c. Nous avons besoin d'utiliser un pseudo-ternaire ici que les comptes pour savoir si $cest -1ou non. Si tel est le cas, nous choisissons .count(c'est-à-dire l'élément final) de $z. Sinon, nous ajoutons simplement l' 0xopérateur hexadécimal $cà une chaîne. Notez qu'il s'agit d'un index zéro.

Cette tranche de tableau a ses éléments -joinédités avec un littéral \xpour former une chaîne. C'est ajouté avec un autre littéral \xet le résultat est laissé sur le pipeline. L'impression est implicite.

Exemple

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
AdmBorkBork
la source
Pouvez-vous accéder au shell avec cette langue?
Addison Crump
@VTCAKAVSMoACE En théorie, étant donné le nouveau sous-système Windows pour Linux , il devrait être possible de diriger les choses ensemble et / ou de passer des paramètres via la ligne de commande. La mise en œuvre est laissée comme un exercice pour le lecteur. ;-)
AdmBorkBork
2

Gelée , 39 38 37 octets

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

Essayez-le en ligne!

Bat maintenant 05AB1E! (malgré le manque de "conversion de hexadécimal" intégré)

Même format d'entrée que la solution de Dennis .

Utiliser , qui est une nouvelle fonctionnalité (abréviation de Ѐ). Sans cela, cela prendrait 38 octets.

user202729
la source
Fonctionne uniquement pour l'entrée avec len jusqu'à 1e9.
user202729
Mais si c'est sur FAT32 (où la taille d'entrée est au maximum de 2 Go) c'est suffisant.
user202729
1

Perl, 114 octets

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

Arguments donnés sur la ligne de commande sous la forme d'une chaîne entre guillemets suivie de deux nombres. Les nombres sont pris en décimal (je sais que hex a été utilisé dans les exemples mais il n'a pas été spécifié dans le post)

Techniquement, ne fonctionne que sur les entrées avec jusqu'à 2 ^ 21 octets car la méthode de sous-chaîne de Perl est idiote

theLambGoat
la source
Apparemment , la plage est inclusive, donc par exemple 7à edevrait se traduire par une chaîne de longueur 32.
Neil
1

Python, 140 octets

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

Fractionne la chaîne d'origine et vide les éléments s'ils contiennent moins de cinq caractères, les préfixe \xet les tranches par les deuxième et troisième arguments.

Version de 162 octets si nous devons gérer d'autres types de sortie non spécifiés par la question:

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']])
atlasologue
la source
Cela ne fonctionnera pas si, par exemple, la dernière ligne ressemble à quelque chose, 00000030: 5858 58 XXXcar elle retirera la dernière partie et vous obtiendrez quelque chose comme \x58\x58\x58\xXX\xX.
AdmBorkBork
@TimmyD Je ne pensais pas que cette affaire devait être traitée, ce qui allait à l'encontre des spécifications du défi.
atlasologue
J'ai lu le défi car le premier argument donné n'est qu'un exemple, donc il pourrait y avoir d'autres xxdsorties utilisées comme argument à la place. "Voici un exemple de ce à quoi ressemblera le premier argument:"
AdmBorkBork
0

Python 2 et 3 - 164 162 150 146 134 150 octets

Accepte désormais les chaînes hexadécimales pour les deuxième et troisième arguments.

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))
plafond
la source
0

Python 3.5, 125 octets

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

Non 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
RootTwo
la source