xxd出力をシェルコードに変換します


15

xxdからいくつかの出力を取得し、手動で使用可能なシェルコードに変換するのは面白くないので、あなたの仕事はプロセスを自動化することです。

ルール

あなたの提出物は、関数、ラムダ、スクリプト、またはそれらの合理的な同等物です。結果を印刷するか、提出物が関数/ラムダである場合、それを返すこともできます。

プログラムは3つの引数を取る必要があります。最初の引数は、次のように、ファイル名以外の引数なしで実行されたxxdの出力を含む文字列ですxxd some_file。最初の引数がどのように見えるかの例を次に示します。

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

バイトを含む中央セクション(の後の最初の8列:)を取得し、空白を削除してシェルコードに変換し、\x各バイトの前にaを置く必要があります。

上記の入力に対する出力は次のとおりです(他の引数は無視します):

\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

最初の引数は常に有効なxxd出力であり、ファイル名以外の引数なしで実行されると想定できます。

また、出力は、バックスラッシュがエスケープ文字として使用されないリテラルのバックスラッシュである文字列である必要があります。したがって、「\ x65」と言うとき、バイト0x65についても、文字「A」についても話していません。コードでは、文字列「\ x65」になります。

2番目の引数は、xxd出力のシェルコードの開始位置を指定し、3番目の引数は終了位置を指定します。3番目の引数がの場合、-1xxd出力の最後で終了します。2番目と3番目の引数も常に負ではありませんが、3番目が-1

以下にテストケースを示します。

引数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

引数2 7:、引数3:(eこれらは両方とも16進数を表す文字列です)

出力: \xc9\xcd\x80\xeb\x16\x5b\x31\xc0

引数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

引数2 0:、引数3:2e

出力: \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

引数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

引数2 a:、引数3:-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

最小バイトのコードが優先されます。受賞者は、2016年8月15日の7日間で発表されます(ただし、それ以降の提出は大歓迎です)。

更新

@Adnan、おめでとうございます!


明確にするために、エントリは文字列を返すことができますか、それとも印刷する必要がありますか?
ヨルダン

関数、ラムダ、またはそのようなものである限り、文字列を返すことは問題ありません(要求後に指定するようにルールを更新しました)。
アディソン16

1
コードが印刷可能な場合、通常のASCIIコードを返すこともできますか?たとえば、の~代わりに\x7e。そして、\t代わりに戻ることができ\x09ますか?
orlp 16

@orlp申し訳ありませんが、一貫した形式である必要があります。
アディソン16

引数は16進数である必要がありますか?また、2番目の例を示した方法は7、ゼロベースのインデックスのように見えe、1ベースのインデックスです(e-7=7ただし、出力には8つの16進コードがあります)か、何かを見落としていますか?
ニール

回答:


5

05AB1E39 38バイト

次の形式で入力します。

arg2
arg3
arg1

コード:

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

説明:

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

CP-1252エンコードを使用します。オンラインでお試しください!


12

Bash + coreutils + xxd、73 71 69バイト

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

STDINのhexdumpおよびstart / endをコマンドライン引数として期待します。

これにより、デフォルトで許可されているいくつかの警告がSTDERRに出力されます。


1
私は誰かがxxd彼らのソリューションで実際に使用することを望んでいました!
アディソン

@addison私はしようとしましたが、私の言語はコマンドライン入力の改行をサポートしていません。:c
アディソンクランプ

私は交換することができる午前16#0x
デジタル外傷

@DigitalTrauma私はそれが何かだと思ったが、xxdどこでも動作するようだ。
デニス

1
はい、bashは0xn16進数スタイルと0m8進数スタイルの番号をそのまま解析します:gnu.org/software/bash/manual/bash.html#Shell-Arithmeticecho $[0x2a] $[052]
デジタル外傷

5

JavaScript、84バイト

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

説明:ダンプの不要な部分をすべて削除し、\x各16進ペアの先頭に追加してから、結果の必要な部分を抽出します。パラメータを||uインクリメントすることで取得したゼロを、文字列の最後までスライスするマジック値であるゼロに変換するために使用されます。およびが16進数の文字列である場合、101バイト:-1undefinedsliceft

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

の代わりに(s,f,t,u)=>、を実行s=>f=>t=>u=>して、数バイトを節約できます。
イスマエルミゲル

@IsmaelMiguel申し訳ありませんが、それは正確に2つの実際のパラメーターを持つ関数でのみ機能します。私の特定のケースでは、uこれは追加のパラメーターである必要があり、カリー化できません。
ニール

@IsmaelMiguelまた、それは実際には長いです...-
ヤコブ

5

Ruby:90 89 87 79 63バイト

@addisonのおかげで-2バイト@PiersMainwaringのおかげで
-8バイト

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

repl.itのテストを参照してください:https ://repl.it/Cknc/5


で置き換え.join*""2バイト節約できます。
アディソン16

に置き換え.map{|h|h.to_i(16)}.map(&:hex)、さらに8バイト節約できます!
piersadrian

ありがとう@PiersMainwaring!それを忘れてばかげている。.hex引数を個別に呼び出す方が短いことが判明したので、実際に16を節約しました!
ヨルダン

4

ゼリー48 44 バイト

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

これは、hexdumpが唯一のコマンドライン引数であり、STDINの終了点と開始点がこの順序で改行で区切られていることを想定しています。

オンラインでお試しください!


これについての説明が見たいです;)
コナーオブライエン

後で追加しますが、少し先にゴルフを試してみます。51バイトのJellyと69バイトのBashは正しくありません
デニス

3

PowerShellのV2 +、175の 157 142 133 129バイト

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

入力を受け取り$a$b$cで、$aリテラル改行で区切られた文字列、またはPowerShellの持ついずれかのように`nラインを分離する文字。ヘルパー文字列を次のように$z処理の重いものとして設定$aします-

まず-split改行で、次に各行で|%{...}中間セクションをスライスし[10..48]、を使用し-ne32てスペースを削除し、-join1つの長い文字列に戻し、-split2文字ごとに(2文字を保持)、-ne''空の要素を削除します。これにより、などの2要素文字列の配列が生成され('31','c0','b0'...)ます。

次に$b、16進演算子を使用したキャストに基づいて、その値までの配列にスライスします$c。私たちは、かどうかを考慮し、ここで疑似三使用する必要が$cある-1かどうかを。そうである場合、の.count(つまり、終了要素)を選択します$z。それ以外の場合は、文字列に0x16進演算子を追加し$cます。これはゼロインデックスであることに注意してください。

その配列スライスには、1つの文字列を形成-joinするリテラル\xと一緒に要素が含まれています。別のリテラルが先頭に追加され\x、結果はパイプラインに残ります。印刷は暗黙的です。

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

この言語でシェルにアクセスできますか?
アディソンクランプ

@VTCAKAVSMoACE理論的には、Linux用の新しいWindows Subsystemを考えると、物事を一緒にパイプしたり、コマンドライン経由でパラメーターを渡したりできるはずです。実装は、読者の課題として残されています。;-)
AdmBorkBork 16

2

ゼリー39 38 37バイト

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

オンラインでお試しください!

05AB1Eに勝ちました!(「16進数から変換」ビルトインがないにもかかわらず)

デニスのソリューションと同じ入力形式。

新しい機能であるを使用します(の略Ѐ)。これがないと、これには38バイトかかります。


lenが1e9までの入力に対してのみ機能します。
user202729

ただし、FAT32(入力サイズが最大2GB)であれば十分です。
user202729

1

Perl、114バイト

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

コマンドラインで引用符付きの文字列として2つの数字が続く引数。数値は10進数で取得されます(例では16進数が使用されていることは知っていますが、投稿では指定されていません)

技術的には、perlのサブストリングメソッドは馬鹿げているため、最大2 ^ 21バイトの入力でのみ機能します。


例えばので、どうやら範囲は、包括的である7e長さ32の文字列を生じるはずである
ニール・

1

Python、140バイト

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

元の文字列を分割し、要素が5文字未満の場合は要素をダンプ\xし、2番目と3番目の引数で先頭に追加し、スライスします。

質問で指定されていない他のタイプの出力を処理する必要がある場合は、162バイトバージョン:

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

たとえば、最後の行が00000030: 5858 58 XXX最後の部分を引き出して、次のようなものを取得するため、最後の行が次のようなものである場合、これは機能しません\x58\x58\x58\xXX\xX
AdmBorkBork

@TimmyDそのケースを処理する必要はないと思い、チャレンジの仕様から外れました。
アトラロジスト

与えられた最初の引数は単なる例であるため、チャレンジを読みました。そのためxxd、代わりに他の出力が引数として使用される可能性があります。「最初の引数がどのように見えるかの例を次に示します。」
AdmBorkBork

0

Pythonの2および3 - 164の162 150 146 134 150バイト

現在、2番目と3番目の引数に16進数の文字列を受け入れます。

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バイト

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

ゴルフをしていない:

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
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.