/avr.png

Shino Channel

ByteCTF2024 Reverse wps

碎碎念 好久没打 CTF 感觉能力退化了不少,遇到不是 Android 的题都有点不会做了,甚至卡了一题光荣成为战犯(?)。想了半天为什么 10 解的题我都不会做,后来发现原来现在还有可以直接去除的 ollvm 混淆…. 平时看到的 ollvm 混淆基本都是加强过的根本没法直接跑轮子去除就根本没往这方面想,还是有点太唐了。 babyAPK 上来肯定是先把 Android 秒了(x 经典 flutter,直接跑一下 blutter。 main.dart 里可以看到一个明显的相关逻辑: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 _ test(/* No info */) { // ** addr: 0x264c0c, size: 0x17c // 0x264c0c: EnterFrame // 0x264c0c: stp fp, lr, [SP, #-0x10]!

Chromium 内核 hook 抓包实战记录

前言 最近正好做到了针对安卓某 APP 内置浏览器抓包相关的东西,顺手记录一下。 目前已有的抓包解决方式可以参考 r0capture 的这个图: https://github.com/r0ysue/r0capture/blob/main/pic/summary2.jpg 其中最为方便的是 HOOK 抓包,不需要配置或导入证书即可获得数据。网络上现有的传统的解决方案为寻找 SSL 库里的 SSL_read 和 SSL_write 函数进行 hook 抓包。这种方法确实可以实现通杀且可以抓到数据,即使是在集成了自定义 SSL 库的内置浏览器中 API 定位也相对简单,但还是存在以下缺陷: 数据包碎片化:由于 hook 的位置较为底层,网络通信较为紊乱,这种方式抓取的流量一般需要借助流量分析软件(如 wireshark)进行进一步分析,在 HTTP2.0 协议的加成下,多个会话的流量占用同一个 TCP 连接进行传输,这使得读写流量的拼接更为复杂繁琐,这对于需要实时批量获取数据的场景是致命的。 无法实现篡改:由于上面的数据包碎片化问题,在攻击者视角下,运用该方法 hook 获取发送的数据包时无法实现实时的数据包篡改和伪造。 针对上述场景,针对内置浏览器使用的 chromium 内核进行了粗略的分析,考虑在浏览器较为上层的位置截取完整的包数据。 Chromium 网络栈 这里首先需要拿出一个经典的八股面试题:在浏览器输入URL 地址回车后,发生了什么? 我们并不关心无聊的八股答案,这里我们主要关注的是 Chromium 具体如何发送一个 HTTP 请求。 这里有一篇文章,懒得复读了: https://www.cnblogs.com/bigben0123/p/12650519.html 虽然这篇文章完全忽略了对 Cache 相关的操作,但是正好我们也不关心那部分内容。 我们的目的是抓到完整的、全量的请求,所以我们需要找一个请求过程中符合以下条件的时机: 请求已经被构建好 请求还没有被交给具体的传输流 前者会导致我们无法获取完整的请求,而后者会导致请求已经根据请求协议被分流,我们只能拿到某种特定协议下的请求包而丢失其他请求。 由于确认第一点十分麻烦,所以我们期望找到的是满足第二点的最下层位置,即请求被交给传输流的前一刻。 经过几小时的坐牢我定位到了类 HttpNetworkTransaction。 https://source.chromium.org/chromium/chromium/src/+/main:net/http/http_network_transaction.cc?q=HttpNetworkTransaction&ss=chromium%2Fchromium 这里我们比较关注的是 HttpNetworkTransaction 发送请求的流程: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 int HttpNetworkTransaction::DoLoop(int result) { DCHECK(next_state_ !

0ctf/tctf2023-0gn nodejs引擎魔改分析

碎碎念 本文也可以改名《Shino 为什么是一个啥比》,一个首波逆向题坐牢两天没做出来(还是我太菜了) 主要是复盘记录一下当时做题的几个思路和分析以及反思,虽然都没有成功但是也算一次经验积累,以供以后参考。 赛时分析 js部分 解混淆 首先格式化一下js,然后简单看一下混淆的大概pattern。 有一个函数表,类似这样(节选) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 var i = { 'kwUyT': '3|6|4|2|0|1|5', 'ayHHB': function(H, I) { return H & I; }, 'gqHZW': function(H, I) { return H & I; }, 'bLOAn': function(H, I) { return H ^ I; }, 'NoEaD': function(H, I) { return H & I; }, 'ZUNMN': function(H, I) { return H ^ I; }, 'HpUmq': function(H, I) { return H ^ I; }, 'GXcYX': function(H, I) { return H ^ I; }, 'fMkag': function(H, I, J) { return H(I, J); }, 'WtIoQ': function(H, I, J) { return H(I, J); } } 这里解混淆的思路是显然的,通过正则或手动将被混淆的函数名直接替换为对应的操作。如:

Hitcon2023 Reverse wps | AK with StrawHat

碎碎念 应该是在 Straw Hat 队认真打的第一场国际赛事吧,可惜半天左右就把逆向全打完了(驾驶员技能发动 我一个人就够了.jpg),有些失望(但是很爽)。 写于 2023-09-09 23:25 离比赛结束还有 1day 左右,但是目前放出的 Reverse 已经全部 AK 了,没事干了写个 Writeups 先。感觉目前放出的 Reverse 难度总体偏易,大概 CrazyArcade < Full Chain - The Blade < LessEQualmore 吧,这里按打题顺序简单写一下复盘。 LessEQualmore 虚拟机的逻辑非常简单,每个指令为 3 个字长a1 a2 a3,假设存在mem[]里 逻辑伪代码大概如下: 1 2 3 4 5 6 7 8 9 10 11 12 if a1 < 0: data = input() else: data = mem[a1] if a2 < 0: output(data) else: mem[a2] = data if mem[a2] <= 0: jmp a3 然后就是逆向字节码了,这个字节码非常复杂,需要考虑一种方法去除我们不需要的指令。可以运用类似编译原理中常量传播的思想,追踪所有与输入数据相关的数据位置,dump一份只和输入相关的指令:

SCTF2023 - SycGson

打开看到 Golang 字样,使用 go_parser 恢复一下符号。 https://github.com/0xjiayu/go_parser 1 2 3 4 5 6 7 v24 = "115.239.215.75"; v25 = 14LL; v26 = "12345"; v27 = 5LL; *((_QWORD *)&v2 + 1) = 2LL; v7 = os_exec_Command(); v12 = os_exec__Cmd_StdoutPipe(v7); 奇妙的逻辑,可以通过字符串判断是 nc 取数据,nc 115.239.215.75 12345 看一眼拿到的数据,形式如下: 1 2 3 4 5 6 7 {1801 [ {1878 1630 {1600 1047 1355}} {1968 1923 {1602 1096 1287}} {1805 1572 {1600 1102 1283}} {1963 1669 {1600 1165 1327}}] 4} 看数据 parse 逻辑,从.

ciscn2023-Pwsh Powershell反混淆对抗实战

碎碎念 ​ 刚进黑灯模式就出了flag,看到还是 0 解题以为可以拿全场唯一解光荣退役了,结果平台的flag配置是烂的,以为 0 解的原因是平台烂直接找运维对线,拉扯了一个小时左右赛后说 pwsh 需要人工验证flag以为其实大家都会做只是没交上,第二天起床一看还真是一血全场只有 2 解。也算光荣退役了? 但是比赛结果一般,打ctf不如闲鱼买flag,整场比赛充斥着国粹这种脑瘫题,不过打不过闲鱼哥还是我太菜了。 Writeups 初步分析 题目备份:https://small.fileditch.ch/s3/ssQpUZIxaIRvkfVeChBp.ps1 一个powershell脚本,先base64后解密再执行,先上手解密base64串 1 2 with open("p4.ps1", "w") as f: f.write(base64.b64decode(code).decode()) 1 2 3 4 $M=@{129693309641433576095262078804193086780='(New-ObJecT sysTEm.Io.COMpResSIoN.DEflATesTReAm( [SyStEM.iO.meMORYsTreaM] [sYSTEm.CoNVErT]::FRoMbASe64StrIng( "1VhNaxxHED3Xv+iDYXZBWuwEArHJwQYTy8gS2CKHiCUHIX/koDiKyMXWf89G8s7Ux6ue7hpN7zqBZKa7qvrVq1fVs+rSt3/o7j/0/wNtH+5eaLt7/ySWktmmbThuTP06bfe1pY0grNUi9fY6tPHOBLYnkec17FuLnpHEY2RyVgsqS5T0kLM+yiyA4CTXSa3yOoO4EoWLS+U6mjtxF2K75DKYVx5LkgBWtpCjUBYE+GdMvFpoCXFswiShhd3ABXQR9mqKxxdje1RGgPmqqWXTICCR7fTEbe1HV7FJv+2yAUYpYq2Pjj....' $t=Read-Host -Prompt "Enter your flag"; [System.Collections.Queue]$tt=([byte[]][char[]]$t|%{$_ -shr 4;$_%16}); iex($M[129693309641433576095262078804193086780]) M太长了这里就不放了,可以看到M是一个字典,对应的是混淆过的powershell脚本,每个key(一串数字)分别对应了一段混淆过的powershell的脚本,尝试解混淆。 混淆分析 混淆方式类似如下,这里给出几个样本: 1 2 3 4 5 6 7 (New-ObJecT sysTEm.Io.COMpResSIoN.DEflATesTReAm( [SyStEM.iO.meMORYsTreaM] [sYSTEm.CoNVErT]::FRoMbASe64StrIng( "....." ) ,[SYSTeM.io.COMpRESSIoN.COmPressiOnmODe]::dECoMprEss ) | FoREaCH-objEct{New-ObJecT sySTem.Io.StReamreAder( $_ , [TexT.