Bugku 杂项 Snowfall

1 题目

http://ctf.bugku.com/challenges/detail/id/318.html

2 题目分析

step1 和 step2 两个 txt,VSCode 打开,可以看到里面有很多空字符(不要用记事本打开,分不出来空格、Tab 和回车)

关于换车和换行,Windows 下是 CRLF,UNIX-like 一般是 LF[1],所以判断换行的标志就是 LF(ASCII 10)。
这是一种名为 Whitespace 编程语言[2],一个名为 Whitelips 的网站可以运行这种代码。
也可以写 Python 代码找出所有的空字符(空格、Tab 和换行),按照空格=0、Tab=1、换行=" "的规则进行连接,代码如下[3]

s = open(r"C:\Users\X\Desktop\step1.txt", "rb").read()

a = ""
for i in s:
    if i == 32:  # 空格
        a += "0"
    elif i == 9:  # tab
        a += "1"
    elif i == 10:  # 换行
        a += " "

print(a)
for i in a.split(" 1 "):
    i = int(i, 2)
    print(chr(i), end="")

可以看到结果是一个以 " 1 "分割的字符串,将每一部分转换成对应对应的 ASCII 码,可以得到一个 key。
OK now you can run whitespace code. By the way, the key is H0wt0Pr1ntAWh17e5p4ceC0de.

用网站运行 step1 的话,也是同样的结果。
image

再把 step2 运行一下,
image
可以看到运行结果是一个 7z 文件,里面还有一个 flag.txt 文件。

如何保存这个压缩包呢?

还是根据上面这位大佬[4]的 wp,需要观察右边堆栈的运行过程,把每次 printc 的结果转换成最终的 7z 文件。

因为网站最终 output 的是字符,没法直接复制来生成 7z 文件,所以稍微改了下网站的 js 代码,使得 printc 可以直接输出转义前的数字:

image

修改前后的代码如下:

//   WsPrintChar: function() {
//     this.run = function(env) {
//       var ch = env.stackPop();
//       env.print(String.fromCharCode(ch));
//       env.register.IP++;
//     };
//     this.getAsm = asmWithNoParam;
//   },

  WsPrintChar: function() {
    this.run = function(env) {
      var ch = env.stackPop();
      env.print(ch);
      env.print(",");
      env.register.IP++;
    };
    this.getAsm = asmWithNoParam;
  },

最终得到结果如下:
image

复制出来,用 Python 转成 7z,

x = [55,122,188,175,39,28,0,4,233,178,103,148,176,0,0,0,0,0,0,0,106,0,0,0,0,0,0,0,205,61,162,91,148,163,10,161,6,123,111,146,195,229,199,77,197,176,226,227,44,177,43,96,161,183,25,95,211,125,221,70,102,117,157,219,2,113,89,134,199,190,90,208,113,2,30,131,134,158,192,184,130,200,49,95,169,69,184,36,202,69,2,69,160,13,36,13,176,115,55,167,181,220,144,24,156,128,159,52,143,64,170,177,64,129,83,122,169,252,159,170,33,201,53,141,86,73,35,149,56,209,111,227,46,146,218,18,60,77,165,23,248,38,213,201,136,18,249,150,90,225,255,195,101,23,65,13,144,238,93,31,150,182,136,40,73,137,105,218,0,3,2,92,123,250,128,137,207,217,187,15,202,154,187,172,229,221,223,77,58,56,62,234,238,175,206,236,90,65,197,234,53,242,98,189,93,69,135,58,1,4,6,0,1,9,128,176,0,7,11,1,0,2,36,6,241,7,1,18,83,15,181,85,78,250,249,198,199,186,171,74,81,185,17,229,245,136,33,33,1,0,1,0,12,128,162,131,85,0,8,10,1,126,78,13,98,0,0,5,1,17,19,0,102,0,108,0,97,0,103,0,46,0,116,0,120,0,116,0,0,0,25,0,20,10,1,0,50,92,151,50,148,119,215,1,21,6,1,0,32,0,0,0,0,0,]

f = b''
for i in x:
    f += i.to_bytes(1, 'big')

out = open("1.7z", "wb")
out.write(f)

打开里面有一个加密的 flag.txt,用上面 step1 的 key 解压,还是一个 Whitespace。

用 Whitelips 运行一下,并没有看到输出,因为这里的堆栈指令是 drop,会弹出栈顶元素,但是并不打印。。。

还是改一下 Whitelips 的 js 代码,出栈的同时转换成字符打印。

//   WsDropTop: function() {
//     this.run = function (env) {
//       env.register.SP--;
//       env.register.IP++;
//     }
//     this.getAsm = asmWithNoParam;
//   },

  WsDropTop: function() {
    this.run = function (env) {
      env.print(String.fromCharCode(env.stackPeek()));
      env.register.SP--;
      env.register.IP++;
    }
    this.getAsm = asmWithNoParam;
  },

重新运行,在 output 可以看到 flag:bugku{F1xAnE5olangPr0gr4mT0Cap7ureTh3F14g}
image


  1. https://www.zhihu.com/question/46542168 ↩︎

  2. https://zh.m.wikipedia.org/wiki/Whitespace ↩︎

  3. https://blog.csdn.net/weixin_45696568/article/details/111413521 ↩︎

  4. https://blog.csdn.net/weixin_45696568/article/details/111413521 ↩︎

原文地址:https://www.cnblogs.com/ainsliaea/p/15781990.html