本来这是我最先参加的一次新生赛,也是第一次正式做题
但没想到 wp 拖了一个学期才整理,太忙了懒得,刚开始也没想法去整理
那时还没有确定个人方向其实也差不多有方向了,毕竟 Misc 和 Web 基本做完了
Misc
A_band
- 引入眼帘的 01
- 2 进制转 16 进制,转 字符,得到 aaencode
- aaencode 解码,base家族
- base32 base58 base64
1 | moectf{Why_s0_many_1nstruments?} |
bell202
- 题目描述
1 | :喂喂?这什么声音?喂?诶我调制解调器放哪了? |
- 其实提示的很明显了,但但是还是太菜,没意识到,找到项目
https://github.com/kamalmostafa/minimodem
- kali 安装 minimodem
1 | apt install minimodem |
4. flag
1 | moectf{zizi_U_he@rd_the_meanin9_beh1nd_the_s0und} |
cccrrc
- crc32 碰撞
1 | import binascii |
- flag
1 | moectf{qwq_crc!} |
hamming
- 汉明码原理
https://www.youtube.com/watch?v=X8jsijhllIA - 以传递信息 hello world 为例
先得到二进制数据
hello wolrd
0110100001100101011011000110110001101111001000000111011101101111011100100110110001100100
发送方对数据进行处理,加入检验位,形成多个 4x4 矩阵,在 2 ^ k 处加入奇偶校验,0 号位总奇偶校验
每 11 bit 数据为一组
0 列 | 1 列 | 2 列 | 3 列 |
---|---|---|---|
0 | |||
1 | 1 | 0 | |
1 | 0 | 0 | |
0 | 0 | 1 | 1 |
1 号位校验 1,3 列中 1 的奇偶,填入 0
2 号位校验 2,3 列中 1 的奇偶,填入 1
4 号位校验 1,3 行中 1 的奇偶,填入 0
8 号位校验 2,3 行中 1 的奇偶,填入 1
0 列 | 1 列 | 2 列 | 3 列 |
---|---|---|---|
0 | 1 | 0 | |
0 | 1 | 1 | 0 |
1 | 1 | 0 | 0 |
0 | 0 | 1 | 1 |
0 号位校验 剩余 位中 1 的奇偶,填入 1
0 列 | 1 列 | 2 列 | 3 列 |
---|---|---|---|
1 | 0 | 1 | 0 |
0 | 1 | 1 | 0 |
1 | 1 | 0 | 0 |
0 | 0 | 1 | 1 |
此时为正确的信息,假设某一位数据(3,3)发生了改变
(当错误位数大于等于 2 时,无法得出正确结论)
0 列 | 1 列 | 2 列 | 3 列 |
---|---|---|---|
1 | 0 | 1 | 0 |
0 | 1 | 1 | 0 |
1 | 1 | 0 | 1 |
0 | 0 | 1 | 1 |
根据 4 个块校验位,可以锁定错误位
0 列 | 1 列 | 2 列 | 3 列 |
---|---|---|---|
1 | 0 | 1 | 0 |
0 | 1 | 1 | 0 |
1 | 1 | 0 | x |
0 | 0 | 1 | 1 |
1 | from secret import mytext#It's in alice's device. We can't know! |
1 | from polar_router import recv_over_weak_noisy_channel#how it works doesn't matter, u don't need this lib, just ignore it |
- 需要利用学到的 haming code 编写 hamming_correct(bitlock)
1 | def hamming_correct(bitblock): |
- flag
1 | moectf{Oh_Bin4ry_Mag1c_1s_s0o_c0O1!} |
hide-and-seek
- ctrl-A ctrl-C ctrl-V
1 | moectf{Hey_U_ve_f0und_m3!} |
Locked_bass
- 两次伪加密,base64 解码
1 | moectf{N0w_th1s_i4_a_b@ss_U_can_u3e_to_pla9} |
Misc 方向指北
- pdf文末 Morse 加密
1 | moectf{WEL2OME_4O_MI3C_1UCKY!} |
nyanyanya
- LSB
1 | moectf{A_go0d_way_t0_h14e_in50rmation_in_ima9e3} |
rabbit
- 文件结尾
1 | U2FsdGVkX1+EPlLmNvaJK4Pe06nW0eLquWsUpdyv3fjXM2PcDBDKlXeKupnnWlFHewFEGmqpGyC1VdX8 |
- rabbit 加密
1 | moectf{We1c0m3_t0_moectf_an7_3n7oy_y0urse1f} |
usb
1 | import json |
what_do_you_recognize_me_by
- png
1 | moectf{You_r4c0gnize_%e!} |
zip 套娃
- 4 位爆破,10 位掩码,伪加密
1 | moectf{!zip_qwq_ZIP} |
小纸条
- 猪圈密码
1 | moectf{ILOVEMYBIGBED} |
想听点啥
- 根据后缀名找到软件,读到flag
1 | moectf{Want_s0me_mor3_mus1c?} |
肥肠简单的取证
- base64 编码过的flag,strings直接搜
1 | moectf{soo0oO0o0O0O_3asy!} |
好像可能会有点难的取证
- volatility -f WIN-S60U4TV3ES2-20221008-092303 --profile=Win7SP1x64 cmdscan,发现利用openssl对文件进行了加密
- 使用镜像挂载工具挂载E01文件,会发现有一个盘被Bitlocker锁定。先不管,复制挂载的系统盘下的recover_key_encryped,使用openssl解密
- openssl enc -aes-128-ecb -d -a -in .\recover_key_encryped -out de.txt -nosalt ,密码为 ‘zhebushikey’ 包括引号
- 理论上来说可以直接加上 -pass pass:‘zhebushikey’,但是我这里总是莫名其妙报bad encrypt
- 解密后得到Bitlock密钥,揭开后看到根目录有flag.txt
- 镜像挂载工具推荐Arsenal Image Mounter,FTK老是有莫名其妙的问题
- 这题同样可以逃课,DiskGenius可以直接恢复出未加密的Bitlock密钥,直接解锁即可
Web
ezhtml
- f12
cookiehead
- 加参
God_of_Aim
- 控制台传参;看js
What are you uploading
- 抓包;前端校验
inclusion
- php伪协议,
1 | php://filter/read=convert.base64-encode/resource=flag.php |
sqlmap_boy
- 如题
怎么说呢,一直不会用sqlmap
ezphp
- 要传入flag,get和post都行,否则会执行 exit($giveme)
- flag的内容不能是flag,否则会执行 exit($getout)
- 这里就出现了矛盾的点:当你传入flag值的时候,原来的flag值会被覆盖掉
怎么解决呢?这就涉及到php中双美元变量和单美元变量的区别了。举例来说,如果已经有单美元变量$ikun=f1ag,那么双美元变量 $$ikun=moectf将会先把里面的$ikun替换成f1ag,因此,双美元变量的赋值语句也就变成了$f1ag=moectf - 知道了这一点,再结合 foreach ($_GET as $key => $value) 这一栏,我们就可以实现变量值的交换
- 注意,这里不能用post传入变量,因为post传入的参数并不能实现变量交换
- 地址栏后加上?moectf=flag&flag=moectf,flag就出来了
- 顺序很重要!必须要先用另一个变量把flag的值储存起来,否则flag一样会被覆盖
- index.php
1 |
|
支付系统要耐心审计啊
- 观察源码,发现程序会将post进callback的data值和最终的data值进行哈希校验,而显然app.secret_key是未知的,不能从这里下手。细看了一阵子发现do_callback里面data的格式有点问题,是直接拼接,又看到有个desc,猜测是通过修改amount, status和desc来使拼接后得到相同的字符串
- 打开burpsuite,访问/pay,并且post进amount和desc。注意此时stastus会被设置为PENDING,也就是1,则此时data后半部分为amonut+‘1’+desc
- 此时,页面被重定向至/transaction?id=1,这里的id就是一会要传进去的id。页面上有你的uuid和一个二维码,扫一下二维码,发现得到的值像是hash加密的值 。又看到/callback部分要求传入hash值,猜测这个就是目前data的hash值
- 注意,程序执行过程中有一次会将status设为FAILED,也就是2。因此我们要让现在amonut+‘2’+desc等于之前的值才行
- 那么,显然amout的结尾要是2,desc则没有要求,最终传入/callback时删去amount结尾的2,然后在desc前面加个1就行
1 | amount="12" status="1" desc="12345" amount+status+desc="12112345" //pay |
- 访问/callback,并将现有的id, user, amount, status, desc, hash全部丢进去,看到返回ok,说明我们做出来了,访问/flag得到flag
- app.py
1 | import os |
Reverse
checkin
- 16 进制
1 | moectf{Enjoy_yourself_in_Reverse_Engineering!!!} |
begin
- 异或比较
1 | a = [116,118,124,122,109,127,98,65,41,107,70,40,106,70,106,41,70,112,119,109,42,107,42,106,109,112,119,126,56,56,56,56,56,100] |
- flag
1 | moectf{X0r_1s_s0_int3r3sting!!!!!} |
EquationPy
- 反编译 .pyc
1 | #!/usr/bin/env python |
- solve
1 | from z3 import * |
D_flat
- C# 逆向,dnSpy
- main
1 | private static void Main() |
- int 转 chr
1 | moectf{D_flate_is_C_sharp!} |
chicken_soup(花指令)
- f5
1 | int __cdecl main(int argc, const char **argv, const char **envp) |
- 跳转 loc_401000 loc_401080 ,发现无法正常识别,花指令
1 | 可以看到就是对输入用loc_401000和loc_401080进行了加密,然后跟unk_403000进行对比。 双击loc_401000可以发现跳转到了汇编代码,IDA拖着大红色,后面有一堆杂乱的数据无法识别,这是因为IDA的分析被花指令扰乱了。 在loc_40100D按U将代码转为未定义的数据,然后在unk_40100E处按C转为代码。40100D处是无用指令,就是它扰乱了IDA的分析,所以我们要将它patch掉。 |
1 | 选中这3句按ctrl+alt+k,输入nop然后点patch,对40100D处的0x90也按C转为代码,然后在loc_401000处按P创建函数,F5就可以得到伪代码。 |
- loc_401000是一个加的操作,即input[i] += input[i + 1];,loc_401080是一个移位的操作,即input[i] = ((input[i] >> 4) | (input[i] << 4)) & 0xff;,就是将每一个字节的前4bit放到后4bit,后4bit放到前4bit。
1 | enc = [0xcd,0x4d,0x8c,0x7d,0xad,0x1e,0xbe,0x4a,0x8a,0x7d,0xbc,0x7c,0xfc,0x2e,0x2a,0x79,0x9d,0x6a,0x1a,0xcc,0x3d,0x4a,0xf8,0x3c,0x79,0x69,0x39,0xd9,0xdd,0x9d,0xa9,0x69,0x4c,0x8c,0xdd,0x59,0xe9,0xd7] |
- flag
1 | moectf{p4tch_pr0gr4m_t0_d3c0mpi1e_it!} |
fake_key(动态调试)
- f5
1 | int __cdecl main(int argc, const char **argv, const char **envp) |
- 这道题比较迷惑的点可能在于IDA的命名问题。实际上line18中Str[i] ^= ::Str[i % v6];所使用的两个Str并不是同一个变量。选中变量名按N可以对其进行重命名。对代码重命名之后可以得到比较清晰的伪代码:
1 | int __cdecl main(int argc, const char **argv, const char **envp) |
- 可以看到首先对输入与密钥进行循环异或,然后加上一个随机数。 双击key会发现是字符串
yunzh1jun
。在line17下断点调试起来程序,双击key,会发现key变成了yunzh1junTCL,trackYYDS
,这才是真正的key。 关于如何获取随机数,可以在line19下断,提取出此时的input数据,然后跑完整个for循环,再提取input数据,两者相减就是生成的随机数。 - exp
1 | enc = [0x15, 0x21, 0x0F, 0x19, 0x25, 0x5B, 0x19, 0x39, 0x5F, 0x3A, |
Art(UPX,异或取模深搜爆破)
- 脱壳 f5
1 | int __cdecl main(int argc, const char **argv, const char **envp) |
- sub_401550是一个SHA1,用来限制多解的情况。整个加密逻辑只有一句,即
input[i - 1] ^= (input[i - 1] % 17 + input[i]) ^ 0x19;
。只有最后一位是已知,所以正常思路应该是从最后一位开始爆破,又由于涉及到多解,所以要使用深搜算法来爆破。但是这个题由于明文第一位已知,所以可以直接从前往后爆破。
1 | check = [0x2, 0x18, 0xf, 0xf8, 0x19, 0x4, 0x27, 0xd8, 0xeb, 0x0, 0x35, 0x48, 0x4d, 0x2a, 0x45, 0x6b, 0x59, 0x2e, 0x43, 0x1, 0x18, 0x5c, 0x9, 0x9, 0x9, 0x9, 0xb5, 0x7d] |
太菜了,后面的已经看不懂 wp 了,不写了
如果您喜欢此博客或发现它对您有用,则欢迎对此发表评论。 也欢迎您共享此博客,以便更多人可以参与。 如果博客中使用的图像侵犯了您的版权,请与作者联系以将其删除。 谢谢 !