将xxd输出转换为shellcode


15

从xxd获取一些输出并将其手动转换为可用的shellcode并不有趣,因此您的工作是使过程自动化。

规则

您提交的内容可以是函数,lambda,脚本或任何合理的等效形式。您可以打印结果,或者如果您提交的是函数/ lambda,则还可以将其返回。

您的程序必须带有三个参数,第一个是包含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”。

第二个参数指定shellcode在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

字节最少的代码获胜。获奖者将在2016年8月15日的7天内宣布(但此后提交的作品仍将受到赞赏)。

更新资料

恭喜@Adnan赢得了挑战!


只是为了澄清一下,条目可以返回字符串还是必须打印它?
约旦

只要它是函数,lambda或类似的东西,返回字符串就可以了(我在询问后更新了规则以指定该字符串)。
addison

1
当代码可打印时,我们还能返回常规的ASCII代码吗?例如,~而不是\x7e。我们可以\t代替\x09吗?
奥尔普

@orlp对不起,它必须采用一致的格式。
艾迪生

参数必须是十六进制的吗?另外,给出第二个示例的方式7看起来像是从零开始的索引,并且e是从一开始的索引(e-7=7但是您的输出中有8个十六进制代码),还是我忽略了什么?
尼尔

Answers:


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上进行十六进制转储,并以命令行参数开头/结尾。

这会向STDERR打印一些警告,默认情况下允许。


1
我希望有人可以xxd在他们的解决方案中使用它!
addison

我尝试过@addison,但是我的lang在命令行输入中不支持换行符。:c
Addison Crump

我可以替换16#0x
Digital Trauma

@DigitalTrauma我认为这是一件xxd事情,但它似乎无处不在。
丹尼斯

1
是的,bash 开箱即用地解析了0xn十六进制样式和0m八进制样式编号:gnu.org/software/bash/manual/bash.html#Shell-Arithmeticecho $[0x2a] $[052]
Digital Trauma

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切到字符串末尾的魔术值。如果ft是十六进制数字字符串,则为101个字节:

(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同样,这实际上要更长一些
Jakob

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个字节。
addison

您可以替换.map{|h|h.to_i(16)}.map(&:hex)以节省8个字节!
Piersadrian

谢谢@PiersMainwaring!我很傻,忘记了这一点。它实际上为我节省了16岁,因为事实证明,单独调用.hex这些参数要短一些!
约旦

4

果冻48 44 字节

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

这期望十六进制转储作为唯一的命令行参数,并且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(即end元素)$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

您可以使用这种语言访问shell吗?
Addison Crump

@VTCAKAVSMoACE从理论上讲,给定适用于Linux的新Windows子系统,应该可以将内容通过管道传递到一起和/或通过命令行传递参数。实施留给读者练习。;-)
AdmBorkBork

2

果冻39 38 37字节

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

在线尝试!

现在击败05AB1E!(尽管缺少内置的“从十六进制转换”功能)

输入格式与Dennis解决方案相同

使用,这是一项新功能(的缩写Ѐ)。没有它,这将占用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 ^ 21字节的输入,因为perl的substring方法很愚蠢


显然的范围是包含性的,所以例如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

分割原始字符串\x,并在第二个参数和第三个参数少于五个字符,prepens 和slice 的元素时转储它们。

如果需要处理问题未指定的其他类型的输出,则为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我认为该案不需要处理,不符合挑战的规格。
Atlasologist '16

我读到了挑战,因为给定的第一个参数只是一个示例,因此可能会有其他xxd输出用作参数。“以下是第一个参数的示例:”
AdmBorkBork,2016年

0

Python 2和3-164162150146134字节

现在接受第二个和第三个参数的十六进制字符串。

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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.