moeCTF2023 wp
MoeCTF wp
Re入门指北

答案事13
base_64
好像是pyc的逆向
装了半天pycdc装不好
直接在线工具算了,得到py:
1 | #!/usr/bin/env python |
exp:
1 | #!/usr/bin/env python |
XOR
直接拖进IDA F5,可以看到伪代码:
1 | __int64 __fastcall main() |
XOR之后的结果是 enc,看看是啥,长度貌似是29?
1 | [0x54, 0x56, 0x5C, 0x5A, 0x4D, 0x5F, 0x42, 0x60, 0x56, 0x4C, 0x66, 0x52, 0x57, 0x09, 0x4E, 0x66, 0x51, 0x09, 0x4E, 0x66, 0x4D, 0x09, 0x66, 0x61, 0x09, 0x6B, 0x18, 0x44] |
可以直接写exp了
1 | flag = "" |
UPX
先exeinfo:
64位,有UPX壳
upx -d 脱壳
找了半天终于找到了程序入口:
1 | __int64 sub_140079760() |
同样是异或
1 | [0x0A, 0x08, 0x02, 0x04, 0x13, 0x01, 0x1C, 0x57, 0x0F, 0x38, 0x1E, 0x57, 0x12, 0x38, 0x2C, 0x09, 0x57, 0x10, 0x38, 0x2F, 0x57, 0x10, 0x38, 0x13, 0x08, 0x38, 0x35, 0x02, 0x11, 0x54, 0x15, 0x14, 0x02, 0x38, 0x32, 0x37, 0x3F, 0x46, 0x46, 0x46, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] |
exp:
1 | flag = "" |
BasicAndriod
先贴个学习链接:
https://blog.csdn.net/CharlesGodX/article/details/86602958
下jeb的时候先跑跑这个玩意试试
关键字符串是Input your flag
准备安卓逆向的环境还是有点麻烦的
用AndriodKiller拿到源码:
1 | package com.doctor3.basicandroid; |
核心还是个异或,可以直接写exp了:
1 | (paramAnonymousView[i] ^ this.this$0.key[(i % this.this$0.key.length)]) != this.this$0.enc[i] |
exp:
1 | enc = [25, 7, 0, 14, 27, 3, 16, 47, 24, 2, 9, 58, 4, 1, 58, 42, 11, 29, 6, 7, 12, 9, 48, 84, 24, 58, 28, 21, 27, 28, 16] |
EQUATION
解方程呗
1 | pip install z3-solver |
这么多方程应该可以自动化提取吧….?去找找
确实有
1 | 1. # z3-gen.py |
有关的函数:
SBYTEn(x, 1) 获取的是 x 的第二个字节,而 SBYTEn(x, 2) 获取的是 x 的第三个字节。这在处理数据结构、解析数据包等情况下可能会有用,但需要注意确保数据的字节顺序和内存对齐等问题。
具体来说,SHIBYTE(x) 的作用是从变量 x 的内存位置开始算起,获取偏移量为0字节的位置上的8位字节(即第一个字节),并返回该字节的值。这与原始代码的 HIGH_IND(x,int8) 宏展开结果一致,因为 HIGH_IND(x,part_type) 始终返回0。
exp:
1 | from z3 import * |
RRRRRc4
还是先字符串找入口
1 | __int64 sub_140079A70() |
有数据:
1 | [0x1B, 0x9B, 0xFB, 0x19, 0x06, 0x6A, 0xB5, 0x3B, 0x7C, 0xBA, 0x03, 0xF3, 0x91, 0xB8, 0xB6, 0x3D, 0x8A, 0xC1, 0x48, 0x2E, 0x50, 0x11, 0xE7, 0xC7, 0x4F, 0xB1, 0x27, 0xCF, 0xF3, 0xAE, 0x03, 0x09, 0xB2, 0x08, 0xFB, 0xDC, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] |
1 | sub_140075052((unsigned int)v5, (unsigned int)v6, (unsigned int)byte_140197260, 38, (__int64)v7, 10); |
这一段是RC4加密用的,byte_140197260是代加密的数据,38应该是长度
1 | strcpy(v7, "moectf2023"); |
v7应该是密钥,长度是10
v5, v6是啥?好像都是0
也就是调用了
RC4Enc(0,0,data,38,”moectf2023”,10)
加密后的data与内存中加完密的内容进行比较。
再来看函数内部:(指针经过自己的判断更改过)
1 | __int64 __fastcall sub_1400795E0(char *a1, char *a2, char *a3, int a4, char *a5, unsigned int a6) |
RC4加解密算法相同,直接用上面的算法
exp:
1 |
|
服了,题都写完了gcc还没安好
SMC
需要动态调试,感觉跟下面这道题比较像:
https://blog.csdn.net/weixin_50166464/article/details/120328333
对代码的加密过程就是下面这段:
1 | for ( i = 0; i < 122; ++i ) |
sub_4014D0 是 .text即代码段,对于代码段的操作确实就肯定是对代码的加密保护了。
至于VertualProtect,是用来设置代码段数据的可写权限的
看到加密代码段的地址后IDA跑script:
1 | import idc |
然后对0x4014D0开始的代码段C键MakeCode得到真正加密的代码:
1 | int __cdecl sub_4014D0(char *Str) |
可以直接写脚本了
exp.py:
1 | data = [0x9F, 0x91, 0xA7, 0xA5, 0x94, 0xA6, 0x8D, 0xB5, 0xA7, 0x9C, 0xA6, 0xA1, 0xBF, 0x91, 0xA4, 0x53, 0xA6, 0x53, 0xA5, 0xA3, 0x94, 0x9B, 0x91, 0x9E, 0x8F, 0x00, 0x00, 0x00] |
junk_code
ida无法F5反编译,看看汇编发现一段一定会发生的跳转,感觉像是花指令,模仿着处理一下:
可能有两个函数需要patch:

第一个:
060E~0612是花指令
但是patch完了会显示堆栈不平衡,先去看看第二个
第二个函数也需要patch,同样处理之后没有出现问题:
1 | BOOL __cdecl sub_460750(char *Str2, signed int MaxCount) |
需要一串数据做异或,但是不知道是什么用的:
1 | [0x39, 0x12, 0x0E, 0x55, 0x39, 0x0C, 0x13, 0x08, 0x0D, 0x39, 0x05, 0x56, 0x02, 0x55, 0x47, 0x47, 0x47, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] |
先看看:
1 | data = [0x39, 0x12, 0x0E, 0x55, 0x39, 0x0C, 0x13, 0x08, 0x0D, 0x39, 0x05, 0x56, 0x02, 0x55, 0x47, 0x47, 0x47, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] |
_th3_junk_c0d3!!!}
是flag的后半部分
先猜猜看 moectf{Y0u_kn0w_th3_junk_c0d3!!!}
不知道对不对,接着写前半部分的patch:

之前patch不对的原因是12处的指令其实只有第一个字节是错的,13地址处的数据不应该被patch
1 | int __cdecl sub_4605D0(char *a1, int a2) |
全部ASCII+5就行
moectf{y0u_rem0v3d
Flag : moectf{y0u_rem0v3d_th3_junk_c0d3!!!}
RUST
逆向出来的主要逻辑处理部分还是比较震撼的:
一点一点看内存字符串是能看出来一些端倪的,写在注释里了:
1 | // local variable allocation has failed, the output may be wrong! |
判断正确的条件好像是v41 != 0
嘶 看了一眼v25开头三个数字,正好是moe啊
那直接猜:
1 | data = [-27, -25, -19, -21,-4,-18 ] |
emm不对,应该不能这么做
做了一晚上 python背大锅,一直不知道怎么取python一个数字的高八位同时保留符号位
其实做的事情就是
1 | HIBYTE(v21.pieces.length) = <&u8_as_core::ops::bit::BitXor<u8>>::bitxor(*(u8 **)&v21.fmt.gap0, 0x88u); |
v21来源于全是负的的v25数组
其他的都是对向量的切片/迭代器/赋值操作,所以就有exp:
1 | unsigned char data[30] = { -27, -25, -19, -21, -4, -18, -13, -38, -3, -5, -4, -41, -6, -19, -2, -41, -1, -31, -28, -28, -41, -22, -19, -41, -23, -1, -18, -3, -71, -11 }; |
ezandroid
jadx下Main Activity在这里:
1 | package com.doctor3.ezandroid; |
引用了本地库的check函数,把Lib下的so文件拖进IDA,感觉下面的函数有点像:
1 | _BOOL4 __cdecl sub_CC0(_BYTE *a1) |
v4地址指向394C
感觉像是在走迷宫,迷宫在内存里:
1 | *(_DWORD *)&v7[119] = __readgsdword(0x14u); |
懂了,#是终点,@是起点,.是什么?好像是15个字符一行
凑一下:
1 | *************** |
还需要是23步:
asdsaassssdddddwwddddwd
ssassssdddddwwddddwdd
sdsaassssdddddwwddddwd
sdsaassssdddddwwddddwdd
sdsaassssdddddwwddddwdd
所以就是
1 | moectf{sdsaassssdddddwwddddwdd} |
楽 上面那个是假的,真的是内存里那个
1 | *************** |
这个是
moectf{ssaassssdddddwwddddwwww}
上面那个还是假的,得看看hint说的了
有个返回值是int的,这个应该才对:
1 | int __cdecl JNI_OnLoad(int a1) |
1 | *************** |
就是
moectf{ssaassssdddddwwddddwwaa}
这个是对的
其实看名字也能看出来:
GUI
虽然但是,我好像得去写数据结构课设了
不管了 先IDA启动
有个correctEncryptedFlag,但是又找不到main在哪了
长得蛮像main的东西:
1 | int __stdcall WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) |
找到业务处理逻辑了:
1 | LRESULT __stdcall sub_F5BF90(HWND hWndParent, UINT Msg, WPARAM wParam, LPARAM lParam) |
这段看着像关键逻辑
1 | int __cdecl sub_F5BE00(int a1, int a2) |
动态调试有 v3 也就是v4的结束地址是dword_6FF392
一看原来是我输入的依托东西,再看看
这个函数好像只是加密?(*v4++ - 5) ^ 0x51
终于出了草
一点一点翻函数,看到一个长得特别像字符串比较的函数,在比较的地方下断点:
到了之后F8单步步过看汇编:
这里四段数据,一段一段拿过来猜,有一段解密之后就是flag:
1 | ;下面直接点击就能看到加密之后的flag |

这60个字节dump下来解密就行了
exp:
1 | data = [0x0039, 0x003B, 0x0031, 0x000F, 0x003E, 0x0030, 0x0027, 0x0013, 0x0001, 0x007D, 0x0070, 0x0070, 0x0003, 0x007D, 0x0038, 0x000E, 0x007A, 0x0023, 0x007C, 0x000B, 0x001A, 0x003C, 0x007D, 0x0039, 0x007F, 0x003C, 0x004D, 0x004D, 0x004D, 0x0029, 0x0000] |
unwind
- 标题: moeCTF2023 wp
- 作者: yansui
- 创建于: 2023-10-24 10:35:25
- 更新于: 2023-10-24 10:34:54
- 链接: http://yansui.xyz/2023/10/24/moectf/
- 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。