Brainfuck

20 年比赛已经出现了好几道 Brainfuck 的 vm pwn 了,补一下 Brainfuck 的知识。

简介

Brainfuck 是一种简单的、可以用最小的编译器来实现的、符合图灵完全思想的编程语言,它是由 Urban Müller 在 1993 年创造的,简称为 bf。Brainfuck 由八种运算符构成,它基于一个简单的机器模型,出了指令,这个机器还包括:一个字节为单位、被初始化为零的数组、一个指向该数组的指针(初始时指向数组的第一个字节)、以及用于输入输出的两个字节流。

指令

字符 含义
> 指针加一
< 指针减一
+ 指针指向的字节的值加一
- 指针指向的字节的值减一
. 输出指针指向的单元的内容
输入内容到指针指向的单元
[ 如果指针指向的单元值为零,向后跳转到对应的]指令的次一指令处
] 如果指针指向的单元值不为零,向前跳转到对应的[指令的次一指令处

Brainfuck 程序可以用下面的替换方法翻译成 C 语言(假设 ptr 是 char* 类型)

Brainfuck 含义
> ++ptr;
< --ptr;
+ ++*ptr;
- --*ptr;
. putchar(*ptr);
, *ptr = getchar();
[ while(*ptr){
] }

例子 Hello World!

在屏幕上打印 “Hello World!” 的程序

++++++++++[>+++++++>++++++++++>+++>+<<<<-]
>++.>+.+++++++..+++.>++.<<+++++++++++++++.
>.+++.------.--------.>+.>.

分析

  1. ++++++++++ ,将 *ptr0 置为 10,用作后面循环的条件。
  2. [>+++++++>++++++++++>+++>+<<<<-] ,循环 10 次,每次执行
*(ptr0 + 1) += 7
*(ptr0 + 2) += 10
*(ptr0 + 3) += 3
*(ptr0 + 4) += 1

当循环完后

*(ptr0 + 1) = 70
*(ptr0 + 2) = 100
*(ptr0 + 3) = 30
*(ptr0 + 4) = 10
  1. >++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>. ,这一串就是通过加减得到每个字母对应的 ascii 码,然后将其打印出来,大致过程如下
初始值:
*(ptr0 + 1) = 70
*(ptr0 + 2) = 100
*(ptr0 + 3) = 30
*(ptr0 + 4) = 10

代码计算过程:
*(ptr0 + 1) = 72 输出 'H'
*(ptr0 + 2) = 101 输出 'e'
*(ptr0 + 2) = 108 输出 'l'
*(ptr0 + 2) = 108 输出 'l'
*(ptr0 + 2)  = 111 输出 'o'
*(ptr0 + 3) = 32 输出 ' '
*(ptr0 + 1) = 87 输出 'W'
*(ptr0 + 2)  = 111 输出 'o'
*(ptr0 + 2)  = 114 输出 'r'
*(ptr0 + 2)  = 108 输出 'l'
*(ptr0 + 2)  = 100 输出 'd'
*(ptr0 + 3) = 33 输出 '!'
*(ptr0 + 4) = 10 输出 '\n'

总结

在 ctf 中,大多是通过程序重新自定义运算符,但是功能还是类似的,知道这点,我们就可以大大减轻逆向分析的难度。

内容来源

维基百科 Brainfuck

posted @ 2020-08-24 16:13  PwnKi  阅读(722)  评论(0编辑  收藏  举报