比较好的教程是here。使用它,你会得到下一个分解:
-
16i - 输入将是十六进制(如bc - ibase=16)
-
[q] - [..] 的意思是字符串。因此,这会将字符串 q 存储到堆栈顶部。通常[....] 是存储以供以后执行的一系列命令(如宏),在这种情况下命令q - 退出。
-
s - 取栈顶并将其存储到由下一个字母标识的寄存器中,因此在这种情况下,[q]sa 一起意味着:将字符串 q 存储到寄存器 a
- 下同,将字符串
ln0=aln100%Pln100/snlbx存入寄存器b
- 下一个
A0D68736142sn,将A0D68736142存入寄存器n。在这种情况下不是字符串,而是因为我们输入了十六进制,所以这是一个十六进制数
以上是一个类似的准备阶段,翻译成通用编程语言:
$a = "q";
$b = "ln0=aln100%Pln100/snlbx";
$n = 0xA0D68736142";
堆栈现在是空的(所有内容都存储在注册表中)。
接下来是最后的计算:
-
l 的意思是从后面的寄存器中取值,并把它放到栈顶,所以lb 的意思是:取寄存器b 的值。
-
x 的意思是:将其作为一系列命令执行 - 在这种情况下,将其读取为 eval "$b";
- 最后一个
q表示退出
现在需要分解ln0=aln100%Pln100/snlbx(寄存器b 的内容 - eval-ing 是什么。)
-
ln - 如上所述,在我们的例子中从寄存器 n 中获取值:十六进制数
- 接下来是一个棘手的部分:
0=a,取栈顶,如果是zero,则执行存储在注册表“a”中的字符串(宏)(在我们的例子中,这是一个“q” -退出),例如喜欢:
if( $n == 0 ) eval "a"; #a contains "q" = quit
- 如果
$n 不为零,则再次获取regsiter n 的内容(ln)(放到栈顶)
- 将数字
100(是十六进制)放到栈顶
-
% 将堆栈顶部的两个数字取模(因此:$n % 0x100)并将其放在堆栈顶部
- 将栈顶打印为 ascii 字符串 (
chr($stack))
-
ln 再次取数 $n (再次,它来到栈顶)
- 将
100 放入堆栈
-
/在栈中除数(结果排在最前面)
-
sn将栈存入$n(替换原来的编号)
-
lbx - 如上所述 - 评估寄存器 b
所以,简而言之:
- 来自存储在
$n中的号码0xA0D68736142,
- 通过
0x100取模得到最后两位数,将其转换为ascii并打印出来,
- 除以
0x100(删除最后两位数)-并将其存储到$n
- 重复直到什么都没有(零)
对于0xA0D68736142,您将获得(使用man ascii)
-
42 - B
-
61 - a
-
73 - s
-
68 - h
-
0D - \r
-
A(作为 0A)-\n
使用 perl 从普通 ascii 字符串创建这样的十六进制字符串
perl -E '$s=reverse("Bash\r\n");$s =~ s/(.)/sprintf("%02x",ord($1))/seg;say uc $s'
打印
0A0D68736142
或
perl -E '$s=reverse("Stackoverflow rocks\n");$s =~ s/(.)/sprintf("%02x",ord($1))/seg;say uc $s'
0A736B636F7220776F6C667265766F6B63617453
和
echo "16i[q]sa[ln0=aln100%Pln100/snlbx]sb0A736B636F7220776F6C667265766F6B63617453snlbxq" | dc
打印:
Stackoverflow rocks
Ps:dc 是一件奇怪的事情 - 它更容易阅读和理解“程序”作为创建一个。 :)