Перетворити xxd вихід у shellcode


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 стовпців після цього :), і перетворити його в shellcode, видаливши будь-який пробіл, а потім поставити \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 результатом, запускається без аргументів, крім імені файлу.

У вашому висновку також має бути рядок, де риски зворотнього косого ряду є буквальними зворотніми косими рисами, а не використовуються як символи втечі. Тому коли я кажу "\ 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 Я намагався, але мій lang не підтримує нові рядки у введенні командного рядка. : 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

Ruby: 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 байт!
— пристань

Дякуємо @PiersMainwaring! Нерозумно мені це забути. Це насправді врятувало мене 16, тому що виявилося коротшим, щоб звертатися .hexдо аргументів окремо!
— Йорданія

4

Желе , 48 44 байт

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

Це очікує, що hexdump буде єдиним аргументом командного рядка, а кінцеві та початкові точки на STDIN у такому порядку розділені рядковим записом.

Спробуйте в Інтернеті!


Я хотів би побачити пояснення цьому;)
— Conor O'Brien

Я додам його пізніше, але спробую спочатку трохи пограти в гольф. 51 байт Jelly vs 69 байт Bash не може бути правильним ...
— Dennis

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рядка. Зауважте, що це нульове значення.

У цьому фрагменті масиву є його елементи -joined разом із літералом, \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 Теоретично, з огляду на нову підсистему Windows для Linux , слід створити об'єднання даних та / або передавати параметри за допомогою командного рядка. Реалізація залишається вправою для читача. ;-)
— AdmBorkBork

2

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

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

Спробуйте в Інтернеті!

Тепер б'є 05AB1E! (незважаючи на відсутність вбудованого "перетворення з шістнадцяткової")

Той самий формат введення, що і рішення Денніса .

Використання Ɱ, що є новою функцією (скорочено для Ѐ). Без цього це займе 38 байт.


Працює лише для введення з len до 1e9.
— користувач202729

Але якщо він знаходиться на FAT32 (де розмір вводу становить не більше 2 Гб), цього достатньо.
— користувач202729

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 є нерозумним


Мабуть, діапазон є інклюзивним, тому, наприклад, має 7вийти eрядок довжиною 32.
— Ніл

1

Пітон, 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']])

Це не спрацює, якщо, наприклад, останній рядок є чимось подібним, 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))

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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.