Answers:
原始代码:
[[ ! "${1////x}" =~ [[:alnum:]] ]]&&[[ $# = 1 ]]&&bash -c "$1"
输入:
__=; (( __++, __-- ));
(( ___ = __, ___++));
(( ____ = ___, ____++));
(( _____ = ____, _____++));
(( ______ = _____, ______++));
(( _______ = ______, _______++));
(( ________ = _______, ________++));
(( _________ = ________, _________++));
${!__##-} <<<\$\'\\$___$______$_______\\$___$______$_____\\$___$_______$__\\$___$_______$_________\'\ \$\'\\$___$___$__\\$___$______$_______\\$___$_______$______\\$___$_______$______\\$___$_______$_________,\ \\$___$____$_________\\$___$_______$_________\\$___$________$____\\$___$_______$______\\$___$______$______\\$__$______$___\'
说明:
这编码为“回声你好,世界!” 作为八进制转义序列(\ xxx)。
除了您也不能使用数字外,因此第一部分为数字0-7建立变量。您可以使用它们来构建具有八进制序列的字符串,这些字符串的计算结果将为您提供实际的命令。
但是eval
也是字母数字。因此,它将此字符串作为输入传递给的另一个实例bash
。$0
包含用于调用Bash的命令的名称,如果您正常运行(通过TIO或通过将其粘贴到终端中),则该名称通常只是bash
(或-bash
用于登录shell)。(顺便说一句,这意味着如果您尝试通过将其粘贴到脚本中来运行它,则由于它尝试分叉多次,事情将变得非常错误。)
但是无论如何,你不能$0
直接说。相反,$__
包含名称的$0
(“0”),并且可以使用间接扩展访问它(${!__}
指中的内容$0
)。
最后,它为您提供了所需的所有部件。
〡㋄ⶐ✐сᑀ⟙ⶐⶐ〡ސЀᶑ〡㋄ⶐ✐сᑀ⟙ⶐⶐ〡ސЀᶑ〡㋄ⶐ✐сᑀ⟙ⶐⶐ〡ސЀᶑ〡㋄ⶐ✐сᑀ⟙ⶐⶐ〡ސЀᶑ〡㋄ⶐ✐сᑀ⟙ⶐⶐ〡ސЀᶑ〡㋄ⶐ✐сᑀ⟙ⶐⶐ〡ސЀᶑ〡㋄ⶐ✐сᑀ⟙ⶐⶐ〡ސЀᶑ〡㋄ⶐ✐сᑀ⟙ⶐⶐ〡ސЀᶑ〡㋄ⶐ✐сᑀ⟙ⶐⶐ〡ސЀᶑ〡㋄ⶐ✐сᑀ⟙ⶐⶐ〡ސЀᶑ〡㋄ⶐ✐сᑀ⟙ⶐⶐ〡ސЀᶑ〡㋄ⶐ✐сᑀ⟙ⶐⶐ〡ސЀᶑ〡㋄ⶐ✐сᑀ⟙ⶐⶐ〡ސЀᶑ
sLƽ$Xṙ5O½Ọ
原始代码可以这样解释:
sLƽ$Xṙ5O½Ọ Main link; argument is z
s Split z into n slices, where n is:
$
ƽ The integer square root of
L the length of z
X Random of a list. Returns a random row of the input put into a square
ṙ5 Rotate the list left 5 times
O Get codepoints
½ Floating-point square root
Ọ From codepoints
因此,只需选择“你好,世界!” 并获得代码点,将它们平方,然后投射回代码点,向右旋转5次,然后对结果进行平方和展平。
不知道这是否是正确的解决方案(在TIO上它会打印\00
字符),但是在我的octave-cli
shell中,它看起来像这样:
同样在最初的挑战中,它说什么也不打印(或null字符),所以如果没有什么相同,\00
那么应该没问题。
[72, 101, 108, 108, 111, 44, 32, 87, 111, 114, 108, 100, 33, 0]
0
一个10
)。
Hello, World!
和换行。” 是挑战的确切报价。确实,这使答案变得微不足道。
{length:1, charCodeAt:()=>(e='Hello, World!', String.fromCharCode=()=>'')}
那很容易。
我注意到任何字符串输入都将无法输出,Hello, World!
因为里面的整个东西String.fromCharCode
只会返回4的倍数,并且!
char码为33。所以很显然,我们只需要破解整个程序即可。如果不尝试阻止内置JavaScript,那么对它们进行黑客攻击就显得微不足道了(即使这样做,通常也有很多解决方法...)。
简单代理,仅在第3次调用时返回所需字符。
var i = 0;
var string = "Hello, World!";
var proxy = new Proxy([], {
get: function(target, property) {
if (!(++i%3)) {
return string[property];
}
return [1];
}
});
魔术输入是: 1767707618171221 30191World!
1767707618171221
为质数,用36为底数写成"hello"
。大写时,产生"Hello"
,使用$><<
$><<", #$'"if/30191/
查找数字30191
,然后将由逗号,空格和输入后的内容组成的字符串写入stdout 30191
(使用$POSTMATCH
,这是其简短的变体,在此引用$'
)。将其作为第一个参数传递:
C=("").char;_G[C(112,114,105,110,116)](C(72,101,108,108,111,44,32,87,111,114,108,100,33))
假设原始代码在file中tehtmi.lua
,运行(在bash或类似的shell中):
lua tehtmi.lua 'C=("").char;_G[C(112,114,105,110,116)](C(72,101,108,108,111,44,32,87,111,114,108,100,33))'
它也可以在TIO使用的Lua 5.3上运行,所以为什么不在线尝试一下呢??我尚未在使用“ PUC-Rio的Lua 5.1”内核的实现上进行过测试(因为我无法真正找到任何信息),但是我的解决方案可能也可以在其中使用。
它以代码形式运行第一个参数,但前提是它包含少于5个小写字符。
诀窍是奔跑print("Hello, World!")
。可以运行的另一种方法是使用_G["print"]("Hello, World!")
,它仅使用字符串。
但是由于小写计数限制,我们不能直接使用字符串,但是,您可以运行("").char
获取函数string.char
,该函数可以将一系列字节转换为字符串。我将其分配给一个大写变量(因此我们没有达到极限),因此我们可以使用它来构造print
和Hello, World!
可以像上面一样使用的字符串。
next
而不是char
因为迭代顺序的随机化而在Lua 5.3上不起作用。
输入必须是包含以下内容的字符串:
e(
`\
_\
=\
>\
"\
H\
e\
l\
l\
o\
,\
\
W\
o\
r\
l\
d\
!\
"\
+\
\`
\`
`)
使用以下方法尝试:
const e=eval,p=''.split,c=''.slice,v=[].every,f=s=>(t=c.call(s),typeof s=='string'&&t.length<81&&v.call(p.call(t,`\n`),l=>l.length<3)&&e(t)(t))
input='e(\n`\\\n_\\\n=\\\n>\\\n\"\\\nH\\\ne\\\nl\\\nl\\\no\\\n,\\\n \\\nW\\\no\\\nr\\\nl\\\nd\\\n!\\\n\"\\\n+\\\n\\`\n\\`\n`)'
console.log(f(input))
如果您不关心输出的尾随换行符要求,则可以用以下内容代替最后6行:
!"
`)
输入的限制是它是一个字符串,每行的长度不超过两个字节,总长度不超过80个字节。我正确理解后的第一次尝试是:
_
=>
`\
H\
e\
l\
l\
o\
,\
\
W\
o\
r\
l\
d\
!
`
注意:\
s将忽略输入字符串中的换行符。这对答案至关重要,而且我无法相信我偶然发现了它。(我以前很熟悉但是却忘记了它)
但这是行不通的,因为=>
必须与参数位于同一行。值得庆幸的是,我的想法是将类似的内容包装在字符串中,并在输入中添加一个eval以将其减少到一行,从而得出最终答案。输入中的eval发生后,将生成以下内容作为字符串(然后将其评估为函数,然后运行):
_=>"Hello, World!"+`
`
这确实很难破解,但最终我成功了。
另外,有史以来第一次破解!
我想这总是很危险的,但是我认为我有一个裂缝,在我正确的解释是因为解释器中有一个错误(我刚刚编译)。
我的输入
0 1 0 1 0 1 0 1 1 0 1 0 0
输出是 Hello, World!\n\n\n\n\n\n\n\n\n\n.....
带有无休止的换行符。
但是我注意到了代码的最后一部分:
:1/1+1$(@6)7
0x0A
以一种令人恐惧的方式将记事本设置为(换行符),读取输入到面7(输入面),然后重复打印6面(记事本面),直到7面为零。如果将面7设置为零,则只能获得一个换行符。但是,我得到了无限的换行符,而我的第13个输入为0,可以通过在循环中插入“来自7面的打印编号”来验证7面始终为零:
:1/1+1$(@6%7)7
然后打印无休止 \n0
对。
我正在看立方github页面上的规范,这种行为看起来很像个bug。将原始程序的最后一个字符从a 7
更改为0
预期的行为。TIO解释器表现出相同的错误行为。
我发现的解决方案大量使用了无法打印的字符,因此尝试将其粘贴到此处效果不佳。输入的字节值是:
109, 89, 4, 121, 3, 11, 8, 29, 37, 38, 27, 25, 72, 4, 4, 4, 3, 3, 3, 4, 4, 37, 3, 27, 4, 3
或者字符串版本在TIO链接的输入字段中可用。
原始程序将在输入中使用不同的字符,然后反转输入并将两个列表的元素相乘。因此,我创建了一个长26个字符的字符串,其中前13个字符是不同的,后13个字符也都出现在前13个字符中,每对索引[i, 26-i]
个字符中乘以 i个字符的字节值Hello, World!
。
原始代码:
#define O(c)(((char**)v)+c)
#define W(c)*(O(c)-**O(2)+x)
main(x,v){puts(W(42));}
参数:
"Hello, World!" ","
说明:
W(c)
正在从参数列表计算字符串的地址以打印出来。它以cth参数(O(c)
)的地址开头,在本例中为第42个参数,然后减去第二个参数(**O(2)
)的第一个字符作为整数偏移量,然后加x
,即参数的数量。
W(c)
使用第二个参数,因此您知道至少需要3个(0、1、2)。然后是“你好,世界!” 可以在第一个参数中输入,然后要解决该参数,您需要一个字符,其ASCII值适合方程式“ 42-x + 3 = 1”。碰巧是“,”。
我覆盖了解析对象的valueOf()
和toString()
方法,因此强制失败并带有TypeError
。
{"valueOf": 7, "toString": 7}
正确的答案是,52768,23
略有涉及。
00 c0 ;load address
20 fd ae jsr $aefd ; checks for comma
20 eb b7 jsr $b7eb ; reads arguments
该代码首先检查逗号(语法是否必要),然后读取两个参数,第一个参数是WORD,将little-endian存储在存储器位置0014和0015中,后者存储在X寄存器中。
8a TXA ;Store second argument into A (default register)
0a ASL ; bitshifts the second argument left (doubles it)
45 14 EOR $14 ; XOR that with the low byte of first argument
8d 21 c0 STA $c021 ; Drop that later in the program
使用我们的输入重写程序,这非常聪明。最终,它在程序结尾重写输出循环的计数器。
45 15 EOR $15 ; XOR that with the high byte of the first argument
85 15 STA $15 ; Put the result in $15
49 e5 EOR #$e5 ; XOR that with the number $e5
85 14 STA $14 ; Put that in $14
这是曲折的部分:
8e 18 d0 STX $d018 ; stores the original second argument in d018
在C64上,d018是非常重要的字节。它存储涉及屏幕输出的事物的参考点。有关更多信息,请参见此处。如果此值输入错误,则会使您的C64崩溃。为了打印必需的大小写混合字母,这需要为$ 17。
现在我们开始输出循环:
a0 00 ldy #$00 ; zeroes out the Y register
b1 14 lda ($14),y ; puts the memory referenced by the byte
; starting at $14 (remember that byte?)
; into the default register
20 d2 ff jsr $ffd2 ; calls the kernal routine to print the char stored in A
c8 iny ; increment Y
c0 0e cpy #$0e ; test for equality with the constant $0e
这个常数就是以前写的。它清楚地确定了循环运行的时间。它恰好是正确的值,但是我们需要再次将0e粘贴在那里。
d0 f6 bne *-8 ; jump back 8 bytes if y and that constant weren't equal
60 rts ; ends the program
剩下的只是我们需要打印的信息,从内存地址c025开始。
因此,它只是遵循那里的数学原理。
$FF
在那里,但随后决定离开它。
正确答案是
8位足够
代码相当复杂,涉及很多自我修改。因此,您可以使用它进行自我破解,而不是对其进行完全逆向工程。
这是一些反汇编的代码,有助于理解发生的情况。语法适用于KickAssembler。
*=$c000 // LOAD ADDRESS
jsr $aefd //checks for a comma
jsr $ad9e /*Reads in an argument. Stores length of it into
$61, with the address of the stored arg in $62-3*/
jsr $b6a3 /*Evaluates the string, leaving the pointer on $22-3
and the length on A*/ //I think
ldy #$00
loop: lda thedata,y
cpy #$01
beq shuffle
cpy #$07
beq shuffle
cpy #$0b
beq shuffle
tricks: jsr output
iny
bne loop
output: eor ($22),y //XOR's A with the y-eth letter of our input
jmp $ffd2 //good old CHROUT, returns to tricks above
thedata: .byte $f0,$48,$fa,$a2, $1c,$6d,$72,$30
.byte $06,$a9,$03,$48,$7c,$a3
shuffle: sta $c048 //drops A in mystery+4, over the constant
lda $c026,y
sta $c045 //overwrites the low byte of mystery
lda $c027,y
sta $c046 //overwrites the high byte of mystery
ldx #$00
mystery: lda $aefd,x
eor #$23
jsr output
iny
inx
cpx #$03
bne mystery
cpy #$0e
bne loop
eor #$1a
sta $d018
rts
像这样标记它足以让我看到代码对一系列隐藏的常量进行XOR,以便打印出所需的内容。由于XOR是可逆的,因此,如果您输入所需的输出,它将告诉您密钥是什么。
所以我换了最后一行
/*from sta $d018
to*/ jsr $ffd2
因此它将打印最后需要的输入,而不是由于输入错误而崩溃。
就是这样!
如果有兴趣,我将进一步破解代码。
vice
drops A in mystery+1, over the constant
” <-实际上是mystery+4
您的标签。代价是字节:)和FWIW,即使在严重的 6502代码中,只要代码从RAM运行,自我修改也是很常见的。
原始代码:
œ?“¥ĊɲṢŻ;^»œ?@€⁸ḊFmṪ⁷
输入:
1,2586391,2949273,3312154,3312154,1134001,362881,2223505,766081,1134001,1497601,3312154,1860601,140
说明:
主要是,有必要了解代码的作用。它要做的第一件事是接收字符串
"!,Word Hel"
(以及换行符以外的所有所需字符),并创建一堆排列的字符。输入指定置换编号,输入中的每一对置换将应用于首先应用第一个置换的字符串排除对。基本上是P2(P1(S)),P2(P2(S),P2(P3(S)),...,P2(PN(S)),P3(P1(S)),...,P3 (PN(S)),... ...,PN(P1(S)),...,PN(PN(S))。这些都连接在一起,然后最后一个输入被重用以占用每个PNth这个大字符串中的字符,所以我取PN = len(S)* N = 10 * N。这意味着我们将采用P2(P1(S))的第一个字符,P3(P1(S)的第一个字符)),一直到PN(P1(S))的第一个字符。为进一步简化,我让P1 = 1(即身份置换),然后选择将“ H”置换为第一个字符的P2就足够了位置,一个将“ e”排列到第一位置的P3,依此类推。幸运的是,小的排列数字(例如已经为PN选择的排列数字)不会影响字符串中的较早字符,因此PN留下“!” 在字符串的开头。(如果不是这样,则仍然可以通过选择其他P1来解决。)
4195875
它尝试将第二个参数打印为字符串,这是我们可以在输入中确定的指针。碰巧的是,在位置存储器中4195875
启动了"Hello, World!\n"
字符串。
该数字是通过print("%p", "Hello, World!");
在之前添加来确定的printf
,将十六进制数字转换为十进制并在原始TIO上进行了尝试。但是,它向我显示了printf
格式字符串。通过尝试一些数字,我发现该字符串位于格式字符串之前。
因此在内存中,它看起来像这样(作为C字符串):
Hello, World!\n\0%2$s\0
这也意味着对编译器的任何更新都可能破坏解决方案。
[1, "HH", 1, "eellloo", 1, ",,", 1, " WWoo", 1, "rr", 1, "ll", 1, "dd", 1, "!!"]
解释有点...
var i = 0;
var string = `"${t}"`;
var answer = "i++?0:q=string";
console.log( f(answer) );
PDO,FETCH_CLASSTYPE
(TIO没有定义PDO类,因此上面的演示使用的是一个键盘)
另一个解决方案:
ReflectionFunction,IS_DEPRECATED