#### 出题思路  
首先很明显这是一个指令抽取壳，dex文件中指令丢失，在so中还原。  
用到的是`inline-hook`,hook`libdvm.so`的`dexFindClass`,在加载类时进行指令还原

抽取的指令,和一些字符串进行加密保存，在`.init`段进行了自解密，算法为rc4,密钥为`havefun`

指令还原后完整的dex执行逻辑为,将`SCTF`类的`b`字段作为密钥,将输入的字符串进行`xxtea`加密后与`SCTF`类的`c`字段比较

值得注意的是在`JNI_OnLoad()`时替换了`SCTF`中的`b`,`c`字段

#### 解题方法  
1\. 硬逆so层，还原字节码  
2\. 众所周知，app既然要运行起来，代码必将加载到内存。所以可以在适当时间将完整的dex从内存中dump出来  
本题可在`d.a.c`的`public static String a(String arg1, String arg2, String
arg3)`方法（点击play按钮后该方法的字节码会加载到内存）`o1`方法执行后`o2`方法执行前将dex dump

### get_up  
第一层smc的秘钥经测试在大部分在线工具站都可以查到  
![](http://roomoflja.cn/wp-
content/uploads/2020/07/upload_3da6d43a46b537c4dfcae58d416047e4.jpg)  
第二层秘钥用了flag前5位`SCTF{`做秘钥

然后进行常规的rc4算法对flag进行加密,rc4秘钥是`syclover`并用其他逻辑运算代替异或来完成数据交换  
```cpp  
{  
i = (i + 1) % 256;  
j = (j + s[i]) % 256;  
s[i] = (s[i] & ~s[j]) | (~s[i] & s[j]);  
s[j] = (s[i] & ~s[j]) | (~s[i] & s[j]);  
s[i] = (s[i] & ~s[j]) | (~s[i] & s[j]);  
t = (s[i] + s[j]) % 256;  
data[k] ^= s[t];  
//printf("%2.2x,", data[k]);  
}  
```

解密只要输入格式符合的字符串再拿到该字符串的密文就可写脚本了

```python  
d=[128, 85, 126, 45, 209, 9, 37, 171, 60, 86, 149, 196, 54, 19, 237, 114, 36,
147, 178, 200, 69, 236, 22, 107, 103, 29, 249, 163, 150, 217]  
s=[128, 85, 126, 45, 209, 18, 62, 176, 35, 31, 136, 150, 12, 45, 211, 76, 24,
173, 161, 202, 16, 210, 66, 101, 89, 25, 172, 177, 142, 197]  
s1='SCTF{aaaaaaaaaaaaaaaaaaaaaaaaa'#输入的flag  
for i in range(len(s)):  
print(chr(d[i]^s[i]^ord(s1[i])),end='')  
# SCTF{zzz~(|3[___]_rc4_5o_e4sy}

```# SECRET

Challenge author: tomadimitrie

Can you tell me a secret?

## Analysis

In this challenge we were given an ELF-64bit named `secret` with no canary, NX
enabled, and PIE is also enabled.

```  
$ file secret; checksec secret  
secret: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically
linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0,
BuildID[sha1]=c218ee479df643755efef28fb34263d506c68e61, not stripped  
[*] '/home/kali/Documents/TFC CTF/secret'  
Arch: amd64-64-little  
RELRO: Partial RELRO  
Stack: No canary found  
NX: NX enabled  
PIE: PIE enabled  
```

Let's try to run it

```  
Tell me a secret  
chicken nugget  
I have already heard that one, sorry  
```

It seems that the program will print `I have already heard that one, sorry` if
the input doesn't match the if condition. Let's open the program using ida to
see what the source code looks like.

```c  
int __cdecl main(int argc, const char **argv, const char **envp)  
{  
char s[8]; // [rsp+0h] [rbp-20h]  
__int64 v5; // [rsp+8h] [rbp-18h]  
__int64 v6; // [rsp+10h] [rbp-10h]  
__int64 v7; // [rsp+18h] [rbp-8h]

setvbuf(_bss_start, 0LL, 2, 0LL);  
puts("Tell me a secret");  
*(_QWORD *)s = 0LL;  
v5 = 0LL;  
v6 = 0LL;  
v7 = 0LL;  
fgets(s, 32, stdin);  
if ( *(_QWORD *)s == -6144092014192636707LL )  
{  
puts("hmm, interesting");  
system("cat flag");  
putchar(10);  
}  
else  
{  
puts("I have already heard that one, sorry");  
}  
return 0;  
}  
```

From the main function, it seems that we need to match the if condition. But
the number is too large, let's see it in the other forms by right click the
number and choose the other forms.

Let's try change it into hexadecimal  
```c  
if ( *(_QWORD *)s == 0xAABBCCDDAABBCCDDLL )  
{  
puts("hmm, interesting");  
system("cat flag");  
putchar(10);  
}  
```

From the hexadecimal, now we know that we can use 0xAABBCCDDAABBCCDD or
0xaabbccddaabbccdd (it is the same) for the input to the challenge and we
don't need to input the `LL`. Let's try input it manually  
```  
$ ./secret  
Tell me a secret  
0xaabbccddaabbccdd  
I have already heard that one, sorry  
```

We know that the input are correct. But it doesn't give the flags. Since the
program are in 64 bit, the layout might not be match. So let's use pwntools
library to pack the input into 64 bit format.

## Exploit

Let's make a solver using python  
```python  
from pwn import *

secret = 0xaabbccddaabbccdd

s = process("./secret")

print(s.recvline())  
s.sendline(p64(secret))  
print(s.recvall().decode())

s.close()  
```

Now we need to do is just run the program to make sure it works!

![](secret_local.png)

Since it works, lets test on remote server by adding host, port and replacing
`s = process("./secret")` to `s = remote(host, port)`

```python  
from pwn import *

host = "server.challenge.ctf.thefewchosen.com"  
port = 1342

secret = 0xaabbccddaabbccdd

s = remote(host, port)

print(s.recvline())  
s.sendline(p64(secret))  
print(s.recvall().decode())

s.close()  
```

Now all we need to do is just run the program  
![](secret.png)

Flag: `TFCCTF{Y0ur_s3cret_1s_s4f3_w1th_m3!}`  

Original writeup (https://github.com/ArjunaAcchaDipa/CTF-
writeups/tree/main/TFC-CTF-2021/secret).