> For the complete documentation index, see [llms.txt](https://firmianay.gitbook.io/ctf-all-in-one/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://firmianay.gitbook.io/ctf-all-in-one/6_writeup/reverse/6.2.8_re_defcampctf2015_entry_language.md).

# 6.2.8 re DefcampCTF2015 entry\_language

* [题目解析](#题目解析)
* [参考资料](#参考资料)

[下载文件](https://github.com/firmianay/CTF-All-In-One/blob/master/src/writeup/6.2.8_re_defcampctf2015_entry_language)

## 题目解析

这是一题标准的密码验证题，输入一个字符串，程序验证对误。

```
$ file entry_language
defcamp_r100: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.24, BuildID[sha1]=0f464824cc8ee321ef9a80a799c70b1b6aec8168, stripped
```

```
$ ./entry_language
Enter the password: ABCD
Incorrect password!
```

为了与 angr 的自动化做对比，我们先使用传统的方法，逆向算法求解，`main` 函数和验证函数 `fcn.004006fd` 如下：

```
[0x00400610]> pdf @ main
/ (fcn) main 153
|   main ();
|           ; var int local_110h @ rbp-0x110
|           ; var int local_8h @ rbp-0x8
|              ; DATA XREF from 0x0040062d (entry0)
|           0x004007e8      55             push rbp
|           0x004007e9      4889e5         mov rbp, rsp
|           0x004007ec      4881ec100100.  sub rsp, 0x110
|           0x004007f3      64488b042528.  mov rax, qword fs:[0x28]    ; [0x28:8]=-1 ; '(' ; 40
|           0x004007fc      488945f8       mov qword [local_8h], rax
|           0x00400800      31c0           xor eax, eax
|           0x00400802      bf37094000     mov edi, str.Enter_the_password: ; 0x400937 ; "Enter the password: "
|           0x00400807      b800000000     mov eax, 0
|           0x0040080c      e8affdffff     call sym.imp.printf         ; int printf(const char *format)
|           0x00400811      488b15500820.  mov rdx, qword [obj.stdin]  ; [0x601068:8]=0
|           0x00400818      488d85f0feff.  lea rax, [local_110h]
|           0x0040081f      beff000000     mov esi, 0xff               ; 255
|           0x00400824      4889c7         mov rdi, rax
|           0x00400827      e8b4fdffff     call sym.imp.fgets          ; char *fgets(char *s, int size, FILE *stream)
|           0x0040082c      4885c0         test rax, rax
|       ,=< 0x0040082f      7435           je 0x400866
|       |   0x00400831      488d85f0feff.  lea rax, [local_110h]
|       |   0x00400838      4889c7         mov rdi, rax
|       |   0x0040083b      e8bdfeffff     call fcn.004006fd            ; 调用验证函数
|       |   0x00400840      85c0           test eax, eax
|      ,==< 0x00400842      7511           jne 0x400855
|      ||   0x00400844      bf4c094000     mov edi, str.Nice_          ; 0x40094c ; "Nice!"
|      ||   0x00400849      e852fdffff     call sym.imp.puts           ; int puts(const char *s)
|      ||   0x0040084e      b800000000     mov eax, 0
|     ,===< 0x00400853      eb16           jmp 0x40086b
|     |||      ; JMP XREF from 0x00400842 (main)
|     |`--> 0x00400855      bf52094000     mov edi, str.Incorrect_password_ ; 0x400952 ; "Incorrect password!"
|     | |   0x0040085a      e841fdffff     call sym.imp.puts           ; int puts(const char *s)
|     | |   0x0040085f      b801000000     mov eax, 1
|     |,==< 0x00400864      eb05           jmp 0x40086b
|     |||      ; JMP XREF from 0x0040082f (main)
|     ||`-> 0x00400866      b800000000     mov eax, 0
|     ||       ; JMP XREF from 0x00400864 (main)
|     ||       ; JMP XREF from 0x00400853 (main)
|     ``--> 0x0040086b      488b4df8       mov rcx, qword [local_8h]
|           0x0040086f      6448330c2528.  xor rcx, qword fs:[0x28]
|       ,=< 0x00400878      7405           je 0x40087f
|       |   0x0040087a      e831fdffff     call sym.imp.__stack_chk_fail ; void __stack_chk_fail(void)
|       |      ; JMP XREF from 0x00400878 (main)
|       `-> 0x0040087f      c9             leave
\           0x00400880      c3             ret
[0x00400610]> pdf @ fcn.004006fd
/ (fcn) fcn.004006fd 171
|   fcn.004006fd (int arg_bh);
|           ; var int local_38h @ rbp-0x38
|           ; var int local_24h @ rbp-0x24
|           ; var int local_20h @ rbp-0x20
|           ; var int local_18h @ rbp-0x18
|           ; var int local_10h @ rbp-0x10
|           ; arg int arg_bh @ rbp+0xb
|              ; CALL XREF from 0x0040083b (main)
|           0x004006fd      55             push rbp
|           0x004006fe      4889e5         mov rbp, rsp
|           0x00400701      48897dc8       mov qword [local_38h], rdi
|           0x00400705      c745dc000000.  mov dword [local_24h], 0
|           0x0040070c      48c745e01409.  mov qword [local_20h], str.Dufhbmf ; 0x400914 ; "Dufhbmf"
|           0x00400714      48c745e81c09.  mov qword [local_18h], str.pG_imos ; 0x40091c ; "pG`imos"
|           0x0040071c      48c745f02409.  mov qword [local_10h], str.ewUglpt ; 0x400924 ; "ewUglpt"
|           0x00400724      c745dc000000.  mov dword [local_24h], 0
|       ,=< 0x0040072b      eb6e           jmp 0x40079b
|       |      ; JMP XREF from 0x0040079f (fcn.004006fd)
|      .--> 0x0040072d      8b4ddc         mov ecx, dword [local_24h]
|      :|   0x00400730      ba56555555     mov edx, 0x55555556
|      :|   0x00400735      89c8           mov eax, ecx
|      :|   0x00400737      f7ea           imul edx
|      :|   0x00400739      89c8           mov eax, ecx
|      :|   0x0040073b      c1f81f         sar eax, 0x1f
|      :|   0x0040073e      29c2           sub edx, eax
|      :|   0x00400740      89d0           mov eax, edx
|      :|   0x00400742      01c0           add eax, eax
|      :|   0x00400744      01d0           add eax, edx
|      :|   0x00400746      29c1           sub ecx, eax
|      :|   0x00400748      89ca           mov edx, ecx
|      :|   0x0040074a      4863c2         movsxd rax, edx
|      :|   0x0040074d      488b74c5e0     mov rsi, qword [rbp + rax*8 - 0x20]
|      :|   0x00400752      8b4ddc         mov ecx, dword [local_24h]
|      :|   0x00400755      ba56555555     mov edx, 0x55555556
|      :|   0x0040075a      89c8           mov eax, ecx
|      :|   0x0040075c      f7ea           imul edx
|      :|   0x0040075e      89c8           mov eax, ecx
|      :|   0x00400760      c1f81f         sar eax, 0x1f
|      :|   0x00400763      29c2           sub edx, eax
|      :|   0x00400765      89d0           mov eax, edx
|      :|   0x00400767      01c0           add eax, eax
|      :|   0x00400769      4898           cdqe
|      :|   0x0040076b      4801f0         add rax, rsi                ; '+'
|      :|   0x0040076e      0fb600         movzx eax, byte [rax]
|      :|   0x00400771      0fbed0         movsx edx, al
|      :|   0x00400774      8b45dc         mov eax, dword [local_24h]
|      :|   0x00400777      4863c8         movsxd rcx, eax
|      :|   0x0040077a      488b45c8       mov rax, qword [local_38h]
|      :|   0x0040077e      4801c8         add rax, rcx                ; '&'
|      :|   0x00400781      0fb600         movzx eax, byte [rax]
|      :|   0x00400784      0fbec0         movsx eax, al
|      :|   0x00400787      29c2           sub edx, eax
|      :|   0x00400789      89d0           mov eax, edx
|      :|   0x0040078b      83f801         cmp eax, 1                  ; 1
|     ,===< 0x0040078e      7407           je 0x400797                  ; = 1 时跳转，验证成功
|     |:|   0x00400790      b801000000     mov eax, 1                   ; 返回 1，验证失败
|    ,====< 0x00400795      eb0f           jmp 0x4007a6
|    ||:|      ; JMP XREF from 0x0040078e (fcn.004006fd)
|    |`---> 0x00400797      8345dc01       add dword [local_24h], 1     ; i = i + 1
|    | :|      ; JMP XREF from 0x0040072b (fcn.004006fd)
|    | :`-> 0x0040079b      837ddc0b       cmp dword [local_24h], 0xb  ; [0xb:4]=-1 ; 11
|    | `==< 0x0040079f      7e8c           jle 0x40072d                 ; i <= 11 时跳转
|    |      0x004007a1      b800000000     mov eax, 0                   ; 返回 0
|    |         ; JMP XREF from 0x00400795 (fcn.004006fd)
|    `----> 0x004007a6      5d             pop rbp
\           0x004007a7      c3             ret
```

整理后可以得到下面的伪代码：

```
int fcn_004006fd(int *passwd) {
    char *str_1 = "Dufhbmf";
    char *str_2 = "pG`imos";
    char *str_3 = "ewUglpt";
    for (int i = 0; i <= 11; i++) {
        if((&str_3)[i % 3][2 * (1 / 3)] - *(i + passwd) != 1) {
            return 1;
        }
    }
    return 0;
}
```

然后写出逆向脚本：

```python
str_list = ["Dufhbmf", "pG`imos", "ewUglpt"]
passwd = []
for i in range(12):
    passwd.append(chr(ord(str_list[i % 3][2 * (i / 3)]) - 1))
print ''.join(passwd)
```

逆向算法似乎也很简单，但如果连算法都不用逆的话，下面就是见证 angr 魔力的时刻，我们只需要指定让程序运行到 `0x400844`，即验证通过时的位置，而不用管验证的逻辑是怎么样的。

完整的脚本如下：

```python
import angr

project = angr.Project("entry_language", auto_load_libs=False)

@project.hook(0x400844)
def print_flag(state):
    print "FLAG SHOULD BE:", state.posix.dump_fd(0)
    project.terminate_execution()

project.execute()
```

Bingo!!!

```
$ python2 solve_angr.py
FLAG SHOULD BE: Code_Talkers
$ ./entry_language
Enter the password: Code_Talkers
Nice!
```

## 参考资料

* <https://ctftime.org/task/1691>


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://firmianay.gitbook.io/ctf-all-in-one/6_writeup/reverse/6.2.8_re_defcampctf2015_entry_language.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
