---
title: Hackme Write-up
wargame_site: https://hackme.inndy.tw
tags: CTF
lang: zh_tw
---
# Hackme Write-up
[TOC]
## Reverse
### helloworld
是一個 ELF32
放到 linux 上跑後,直覺猜只是一個猜數字的程式
應該猜對就噴 flag 出來
簡單用 strings 查看會不會直接有 flag,並沒有
用 radare2 打開看看
```
# 用 radare2 打開
r2 helloworld
# 分析一下
[0x08048370]> aa
# 跳到 main
[0x08048370]> s main
# 反組譯這個 function
[0x0804846b]> pdf
```

可以看到在 0x080484dd 的 jne 會跳到輸出 "Try Hard." 的部分
在這個條件判斷的再前面一點應該會有什麼 cmp
果然就在正上方有一個 `cmp eax, 0x12b9b0a1`
再往前追 eax 是啥
就會找到正上方一行 `mov eax, dword [var_10h]`
再找 var_10h 的值會被什麼決定

有個 scanf
第一個參數是 0x80485e7
```
# 到 0x80485e7
[0x0804846b]> s 0x80485e7
# 看一下字串
[0x080485e7]> ps
%d
```
第二個參數是 eax, 而前面的 `lea eax, [var_10h]` 讓 eax 等於 var_10h
所以現在得知 eax 就是我們輸入的 int 數字
0x12b9b0a1 = 314159265
輸入這數字就解會輸出 flag 囉
### simple
是一個 ELF32
執行完後,大概知道要輸入完全正確的 flag
那就找找比較輸入與正確解答的部分在哪
就可以找到正確解答
用 radare2 打開看看
```
# 用 radare2 打開
r2 simple-rev
# 分析一下
[0x080483b0]> aa
# 跳到 main
[0x080484ab]> s main
# 反組譯這個 function
[0x080484ab]> pdf
```

最下面可以看到輸出 flag 的區段
var_4ch 會放 flag
往前找 var_4ch 的值是啥

結果原來是輸入的東西,沒這麼簡單
這裡還得知 輸入最長是 63 個字
回到輸出 flag 的區段
往前看要怎樣才能進這個區段

比較在 var_8ch 的字串跟 `UIJT.JT.ZPVS.GMBH` 要一樣才會進
再往前看 var_8ch 的字串是啥

有往前跳的 jne,九成九是迴圈結構
一開始 `mov dword [var_ch], 0`
再來 `jmp 0x804853a`
`lea edx, [var_4ch]` 讓 edx 指向輸入字串的頭
`mov eax, dword [var_ch]` 讓 eax 等於 index
`add eax, edx` 讓 eax 指向輸入字串第 index 個字
`movzx eax, byte[eax]` 讀出第 index 個字
還不是 0,也就是字串的結尾,就 `jne 0x80484ef`
- 如果這字不是 0xa ('\n')
將這字 +1 並存到 var_8ch + index
++index
- 否則
把輸入字串的第 index 個字清空成 0
將 var_8ch + index 也清空成 0
那只要把 `UIJT.JT.ZPVS.GMBH` 的各字元 ASCII code - 1 就是答案囉
### pyyy
載下來是一個 .pyc 檔
先把這中間碼轉回 .py
工具: https://github.com/rocky/python-uncompyle6
```
uncompyle6 pyyy.pyc > pyyy.py
```
然後裡面程式好醜

line 21 跟 30 可以看到超恐怖的東西
後來嘗試搞懂了 line 21 的鬼之後就沒毅力再去搞懂 line 30 的了 lol
關於 line 21, 有興趣可以看 github 上的 [wtf.py](https://github.com/LJP-TW/CTF/blob/master/Hackme/Reversing/pyyy/wtf.py), 有一步步的簡單化這句鬼的過程
為此還寫了一篇 [Python WTF](https://hackmd.io/@LJP/SyGlwUxSH/edit)
總之,這是 reverse
你可以爆改程式邏輯
在 line 23 前加一句
```python
c = l
```
問題就都沒囉
### accumulator
觀察了一下
發現邏輯是將使用者輸入用 SHA-512 hash 後
分別把 HASH 跟 原輸入 丟進 function 0x004008c0
0x004008c0 是跑類似以下程式碼
```c=
static int accumulator = 0;
static int secretarray[??]; // 要比對的 array
static int index = 0;
char *input; // 要驗證的 input
int length; // 要驗證的長度
for (char *i = input;
(int)input != (int)input + length;
++i)
{
accumulator += (*input);
if (secretarray[index++] != accumulator)
// 輸ㄌ
}
// 贏ㄌ
```
secret array 位在 0x601080

因為 SHA-512 是 64bytes
所以 secretarray 前 64 個元素是 for hash
剩下的元素是 for 原輸入
所以只要把原輸入的 secretarray 拿出來反推就可以推出答案嚕
### GCCC
這題後面的備註是
> Maybe you should try some z3 magic.
>
z3 是啥?
查了一下資料, 有點類似你給一堆條件, z3 會算出一個能滿足條件的一組解出來
中國網站講 z3 是**約束求解器**, 你給他一堆**約束**, z3 能算出一組在此**約束**下的解
以下簡單截圖

安裝只要這樣就好
```
pip install z3-solver --user
```
好, 回頭看題目
這次選用的工具是 dotPeek, 可以反編 .NET framwork 的程式, 超爽der
畫面類似醬子

主要 Logic 就在這裡

要如何寫成**條件**讓 z3 求解哩?
看 [solve.py](https://github.com/LJP-TW/CTF/blob/master/Hackme/Reversing/GCCC/solve.py) ㄅ
為何 result 要訂為 33 bits 而不訂 32 bits 勒?
看 [z3tricky.py](https://github.com/LJP-TW/CTF/blob/master/Hackme/Reversing/GCCC/z3tricky.py) ㄅ
似乎最左邊的 bit 是什麼決定了 z3 中右移時要補什麼
Test1 中, 因為 a 是 32 bits, 0x80000000 最左邊 bit 是 1
右移後, 可以看到在 b 左邊補了 1
Test2 中, 因為 c 是 33 bits, 0x80000000 最左邊 bit 是 0
右移後, 可以看到在 d 左邊補了 0
可能就是這個 ~~Bug~~Feature 影響了 [solve.py](https://github.com/LJP-TW/CTF/blob/master/Hackme/Reversing/GCCC/solve.py) 中第 21 行的 constraint
詳細 z3 怎用可以看 [z3 python API](https://z3prover.github.io/api/html/namespacez3py.html)
<style>
/* fix mathjax rwd scroll
* #Research-direction > simple model
*/
ul > li > .mathjax {
width: 100%;
overflow-x: scroll;
overflow-wrap: break-word;
display: inline-block;
}
/* Dark mode */
/* <!-- todo: fix highlight.js blocks; some code blocks do not render correctly --> */
body {
background-color: #23272a !important;
}
.ui-view-area {
background: #23272a;
color: #ddd;
}
.ui-toc-dropdown {
background-color: #23272A;
border: 1px solid rgba(255,255,255,.15);
box-shadow: 0 6px 12px rgba(255,255,255,.175);
}
.ui-toc-dropdown .nav > li > a {
color: #ccc;
}
.ui-toc-dropdown .nav > .active:focus > a,
.ui-toc-dropdown .nav > .active:hover > a,
.ui-toc-dropdown .nav > .active > a {
color: #bbb;
}
.ui-toc .open .ui-toc-label {
color: #777;
}
table * {
background-color: #424242;
color: #c0c0c0
}
button,
a {
color: #64B5F6;
}
a:hover,
a:focus {
color: #2196F3;
}
a.disable,
a.disable:hover {
color: #EEEEEE;
}
/* Dark mode code block */
/* Imported from titangene/hackmd-dark-theme */
.markdown-body pre {
background-color: #1e1e1e;
border: 1px solid #555 !important;
color: #dfdfdf;
font-weight: 600;
}
.token.operator, .token.entity,
.token.url, .language-css .token.string,
.style .token.string {
background: unset;
}
/* Dark mode alert boxes */
.alert-info {
color: #f3fdff;
background: #40788A;
border-color: #2F7A95;
}
.alert-warning {
color: #fffaf2;
background: #936C36;
border-color: #AE8443;
}
.alert-danger {
color: #fff4f4;
background: #834040;
border-color: #8C2F2F
}
.alert-success {
color: #F4FFF2;
background-color: #436643;
border-color: #358A28;
}
/* Stylized alert boxes */
.alert-danger>p::before {
content: "❌ Dangerous\A";
}
.alert-warning>p::before {
content: "⚠ Warning\A";
}
.alert-info>p::before {
content: "ℹ Information\A";
}
.alert-warning>p::before,
.alert-danger>p::before,
.alert-info>p::before {
white-space: pre;
font-weight: bold;
}
</style>
<style>
/*
* Visual Studio 2015 dark style
* Author: Nicolas LLOBERA <nllobera@gmail.com>
*/
.hljs {
display: block;
overflow-x: auto;
padding: 0.5em;
background: #1E1E1E;
color: #DCDCDC;
}
.hljs-keyword,
.hljs-literal,
.hljs-symbol,
.hljs-name {
color: #569CD6;
}
.hljs-link {
color: #569CD6;
text-decoration: underline;
}
.hljs-built_in,
.hljs-type {
color: #4EC9B0;
}
.hljs-number,
.hljs-class {
color: #B8D7A3;
}
.hljs-string,
.hljs-meta-string {
color: #D69D85;
}
.hljs-regexp,
.hljs-template-tag {
color: #9A5334;
}
.hljs-subst,
.hljs-function,
.hljs-title,
.hljs-params,
.hljs-formula {
color: #DCDCDC;
}
.hljs-comment,
.hljs-quote {
color: #57A64A;
font-style: italic;
}
.hljs-doctag {
color: #608B4E;
}
.hljs-meta,
.hljs-meta-keyword,
.hljs-tag {
color: #9B9B9B;
}
.hljs-variable,
.hljs-template-variable {
color: #BD63C5;
}
.hljs-attr,
.hljs-attribute,
.hljs-builtin-name {
color: #9CDCFE;
}
.hljs-section {
color: gold;
}
.hljs-emphasis {
font-style: italic;
}
.hljs-strong {
font-weight: bold;
}
/*.hljs-code {
font-family:'Monospace';
}*/
.hljs-bullet,
.hljs-selector-tag,
.hljs-selector-id,
.hljs-selector-class,
.hljs-selector-attr,
.hljs-selector-pseudo {
color: #D7BA7D;
}
.hljs-addition {
background-color: #144212;
display: inline-block;
width: 100%;
}
.hljs-deletion {
background-color: #600;
display: inline-block;
width: 100%;
}
</style>