hrh123 发表于 2023-9-27 19:57

BrainFuck转C语言小程序

本帖最后由 hrh123 于 2023-9-27 20:07 编辑

# BrainFuck转C

## 前言

今天看到了帖子
> 记一次brainfuck的解密思路
> <https://www.52pojie.cn/thread-1441720-1-1.html>
> (出处: 吾爱破解论坛)

我居然才知道这语言竟然还能和脱壳破解挂上钩,这帖子里是将brainfuck转了python分析,我技术差,就转c,并稍微完善了下(相当于一个简单的解释器了)

~~本来想着和那贴一样发到脱壳破解区的,后来想想就这么简单个小程序就不碰瓷论坛技术大区了~~

## Brainfuck简介

它是一种是一种极小化的程序语言,一种简单的,可以用最小的编译器来实现的,符合图灵完全思想的编程语言,后缀*一般*为`.brainfuck`或`.bf`
它只有8个运算符,即

+ `>`或`<` : 指针加减1
+ `+`或`-` : 指针所指的字节的值加减1
+ `,`或`.` : 读取或输出指针所指字节内容(ASCII码)
+ `[`或`]` : 若指针所指字节的值为零,则向前/后跳转,跳转到其对应的`[`或`]`的下一个指令处

## 代码实现

### 实现命令行读取

这部分代码异常简单,我这里只有sys库提供的功能实现

```python
import sys

if len(sys.argv) == 1:
    print(f"Usage: {sys.argv} input_file output_file")
    sys.exit(1)
elif len(sys.argv) != 3 and len(sys.argv) != 2:
    print("no input files")
    sys.exit(1)

input_file = sys.argv
try:
    output_file = sys.argv
except IndexError:
    output_file = "a.c"

try:
    with open(input_file, "r") as in_file:
      program = in_file.read()
except IOError:
    print(f"Cannot open input file: {input_file}")
    sys.exit(2)
```

### 转化部分

根据刚才的对于运算符的解释,我们很容易得到它与c语言的对应关系,那么我先准备了一个字典,当然我这里使用了typing库来做了一些增加可读性的操作

```python
from typing import Dict, List

CHAR_TO_OUTPUT: Dict = {
    ">": "\t++ptr;\n",
    "<": "\t--ptr;\n",
    "+": "\t++*ptr;\n",
    "-": "\t--*ptr;\n",
    ".": "\tputchar(*ptr);\n",
    ",": "\t*ptr = getchar();\n",
    "[": "\twhile (*ptr) {\n",
    "]": "\t}\n",
}
```

继续往下,我定义了一个列表来存放输出并添加必要的头文件和声明,以及定义一个长度为30000的字符数组`array`和一个指针`ptr`,用来模拟bf的内存空间

```python
output: List = []

output.append("#include <stdio.h>\n\n")
output.append("int main(void)\n")
output.append("{\n")
output.append("\tchar array = {0};\n")
output.append("\tchar *ptr = array;\n\n")
```

接下去,刚才已经定义好字典了,那我们只需简单的用循环来遍历bf的程序,并使用`CHAR_TO_OUTPUT`字典来获取对应的字符串,然后添加到`output`就好了

```python
for c in program:
    if c in CHAR_TO_OUTPUT:
      output.append(CHAR_TO_OUTPUT)
```

最后,添加一些必要的结束语句,并将列表中的元素用换行符连接起来就好了

```python
output.append("\n\treturn 0;\n")
output.append("}\n")

output_str = "\n".join(output)
```

### 结束

当然也不要忘了对输出文件做处理

```python
try:
    with open(output_file, "w") as out_file:
      out_file.write(output_str)
except IOError:
    print(f"Cannot open output file: {output_file}")
    sys.exit(3)

sys.exit(0)
```

## 示例

用一个简单的HelloWorld程序测试下

```brainfuck
++++++++++[>+++++++>++++++++++>+++>+<<<<-]
>++.>+.+++++++..+++.>++.<<+++++++++++++++.
>.+++.------.--------.>+.>.
```

来到终端

```text
PS \BrainFuck> python main.py hello.bf hello.c
PS \BrainFuck> gcc hello.c -o hello
PS \BrainFuck> ./hello
Hello World!
PS \BrainFuck>
```

测试成功!

## 完整代码

```python
import sys
from typing import Dict, List

CHAR_TO_OUTPUT: Dict = {
    ">": "\t++ptr;\n",
    "<": "\t--ptr;\n",
    "+": "\t++*ptr;\n",
    "-": "\t--*ptr;\n",
    ".": "\tputchar(*ptr);\n",
    ",": "\t*ptr = getchar();\n",
    "[": "\twhile (*ptr) {\n",
    "]": "\t}\n",
}
if len(sys.argv) == 1:
    print(f"Usage: {sys.argv} input_file output_file")
    sys.exit(1)
elif len(sys.argv) != 3 and len(sys.argv) != 2:
    print("no input files")
    sys.exit(1)

input_file = sys.argv
try:
    output_file = sys.argv
except IndexError:
    output_file = "a.c"

try:
    with open(input_file, "r") as in_file:
      program = in_file.read()
except IOError:
    print(f"Cannot open input file: {input_file}")
    sys.exit(2)

output: List = []

output.append("#include <stdio.h>\n\n")
output.append("int main(void)\n")
output.append("{\n")
output.append("\tchar array = {0};\n")
output.append("\tchar *ptr = array;\n\n")

for c in program:
    if c in CHAR_TO_OUTPUT:
      output.append(CHAR_TO_OUTPUT)

output.append("\n\treturn 0;\n")
output.append("}\n")

output_str = "\n".join(output)

try:
    with open(output_file, "w") as out_file:
      out_file.write(output_str)
except IOError:
    print(f"Cannot open output file: {output_file}")
    sys.exit(3)

sys.exit(0)
```

Sogrey 发表于 2023-9-27 23:55

亲测有效。最近在重学c++,这样的程序还挺新鲜的
页: [1]
查看完整版本: BrainFuck转C语言小程序