Конвертировать вывод xxd в шеллкод

15

Взять какой-то вывод из xxd и превратить его в пригодный для использования шелл-код вручную неинтересно, поэтому ваша задача - автоматизировать процесс.

правила

Ваше представление может быть функцией, лямбда-выражением, сценарием или любым разумным эквивалентом. Вы можете распечатать результат, или если ваше представление является функцией / лямбда-выражением, вы также можете вернуть его.

Вы программа должна принимать три аргумента, первый из которых строка , содержащая вывод 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перед каждым байтом.

Вот что должен быть вывод для ввода выше (игнорируя любые другие аргументы):

\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-выводом, без аргументов, кроме имени файла.

Ваш вывод также должен быть строкой, в которой обратные косые черты являются буквальными обратными косыми чертами, а не используются в качестве escape-символов. Поэтому, когда я говорю «\ x65», я не говорю о байте 0x65 или даже о букве «A». В коде это будет строка "\ x65".

Второй аргумент указывает, где в выводе xxd должен начинаться шелл-код, а третий указывает, где он должен заканчиваться. Если третий аргумент есть -1, он закончится в конце вывода xxd. Второй и третий аргументы также всегда будут неотрицательными, кроме случаев, когда третий-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(обе строки представляют шестнадцатеричные числа)

Выход: \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

Код с наименьшим количеством байтов выигрывает. Победитель будет объявлен через семь дней, 15 августа 2016 г. (но заявки после этого по-прежнему приветствуются).

Обновить

Поздравляю @Adnan, чтобы выиграть вызов!

аддисон
источник
Просто чтобы уточнить, могут ли записи возвращать строку или они должны ее печатать?
Иордания
Возврат строки - это нормально, если это функция, лямбда или что-то в этом роде (я обновил правила, чтобы указать это после того, как вы спросили).
Аддисон
1
Можем ли мы также возвращать обычные коды ASCII, когда код печатается? Например, ~вместо \x7e. И можем ли мы вернуться \tвместо \x09?
orlp
@orlp Извините, нет, он должен быть в согласованном формате.
Аддисон
Должны ли аргументы быть в шестнадцатеричном формате? Кроме того, способ, которым вы дали второй пример, 7выглядит как индекс , начинающийся с нуля, и eявляется индексом, основанным на единицах ( e-7=7но в вашем выводе есть 8 шестнадцатеричных кодов), или я что-то пропускаю?
Нил

Ответы:

5

05AB1E , 39 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`

Ожидает hexdump на STDIN и start / end в качестве аргументов командной строки.

Это выводит некоторые предупреждения в STDERR, что разрешено по умолчанию.

Деннис
источник
1
Я надеялся, что кто-то действительно использует xxdих решение!
Аддисон
@addison Я пытался, но мой язык не поддерживает переводы строк при вводе командной строки. : c
Аддисон Крамп
Я могу заменить 16#на 0x?
Цифровая травма
@DigitalTrauma Я думал, что это xxdвещь, но, похоже, работает везде.
Денис
1
Да, bash анализирует 0xnшестнадцатеричные и 0mвосьмеричные номера стилей из коробки: gnu.org/software/bash/manual/bash.html#Shell-Arithmetic . echo $[0x2a] $[052],
Цифровая травма
5

JavaScript, 84 байта

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

Объяснение: Удаляет все ненужные части дампа, добавляется \xк каждой шестнадцатеричной паре, затем извлекает желаемую часть результата. ||uиспользуется для преобразования нуля, полученного путем увеличения -1параметра, в undefinedкоторый входит магическое значение, которое приводит sliceк срезу до конца строки. 101 байт, если fи tявляются строками шестнадцатеричных цифр:

(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 Извините, это работает только для функции с двумя фактическими параметрами. В моем конкретном случае uдолжен быть дополнительный параметр и не может быть карри.
Нил
@IsmaelMiguel Кроме того, это на самом деле больше ...
Якоб
5

Рубин: 90 89 87 79 63 байта

-2 байта благодаря @addison
-8 байтов благодаря @PiersMainwaring

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

Смотрите тесты на repl.it: https://repl.it/Cknc/5

Иордания
источник
Вы можете заменить .joinна, *""чтобы сохранить 2 байта.
Аддисон
Вы можете заменить .map{|h|h.to_i(16)}на, .map(&:hex)чтобы сохранить еще 8 байтов!
piersadrian
Спасибо @PiersMainwaring! Глупо с моей стороны забыть это. Это на самом деле спасло меня 16, потому что оказалось, что короче вызывать .hexаргументы индивидуально!
Иордания
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для удаления пробелов, -joinобратно в одну длинную строку, -splitкаждые два символа (сохраняя два символа) и -ne''для удаления пустых элементов. Это приводит к массиву двухэлементных строк, например ('31','c0','b0'...).

Затем мы разрезаем этот массив на основе $bприведения с шестнадцатеричным оператором до значения $c. Мы должны использовать псевдо-троичный здесь, который объясняет, $cесть -1или нет. Если это так, мы выбираем .count(т.е. конечный элемент) из $z. В противном случае мы просто добавляем 0xшестнадцатеричный оператор $cв строку. Обратите внимание, что это с нулевым индексом.

Этот фрагмент массива имеет свои элементы, -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
AdmBorkBork
источник
Можете ли вы получить доступ к оболочке с этим языком?
Аддисон Крамп
@VTCAKAVSMoACE Теоретически, с учетом новой подсистемы Windows для Linux , должна быть возможность передавать данные вместе и / или передавать параметры через командную строку. Реализация оставлена ​​в качестве упражнения для читателя. ;-)
AdmBorkBork
2

Желе , 39 38 37 байт

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

Попробуйте онлайн!

Теперь бьет 05AB1E! (несмотря на отсутствие встроенной функции преобразования из шестнадцатеричного числа)

Тот же формат ввода, что и у решения Денниса .

Используйте , что является новой функцией (сокращение от Ѐ). Без этого это заняло бы 38 байтов.

user202729
источник
Работает только для ввода с длиной до 1e9.
user202729
Но если он на FAT32 (где размер входного файла не более 2 ГБ), этого достаточно.
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 ^ 21 байт, так как метод подстроки perl глуп

theLambGoat
источник
По- видимому диапазон включена, таким образом, например , 7чтобы eдолжны привести строку длиной 32.
Neil
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

Разбивает исходную строку и выводит элементы, если они меньше пяти символов, добавляет \xи разделяет по второму и третьему аргументам.

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']])
atlasologist
источник
Это не будет работать, если, например, последняя строка будет похожа, 00000030: 5858 58 XXXтак как она вытянет последнюю часть, и вы получите что-то вроде \x58\x58\x58\xXX\xX.
AdmBorkBork
@TimmyD Я не думал, что это дело должно быть рассмотрено, исходя из спецификаций испытания.
атласолог
Я прочитал вызов, так как данный первый аргумент является лишь примером, поэтому xxdвместо него могут использоваться другие выходные данные. «Вот пример того, как будет выглядеть первый аргумент:»
AdmBorkBork
0

Python 2 и 3 - 164 162 150 146 134 150 байтов

Теперь принимает шестнадцатеричные строки для второго и третьего аргументов.

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))
ceilingcat
источник
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']])

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
RootTwo
источник