MIsc:流量分析
这道题,在比赛的时候就差个key了,但是没想到要改高度,后来群里师傅说了下,就再试试,
导出来改高度。
导出来,把
把%5c(4)前面的hex删掉,改成png,就直接拿去那个img-add_info里面出现的,就ok了
转acsii就出来了
web:滴~~~~~~
这道题是我朋友教我的。看到这里就有个文件读取,
然后,看了下源代码,发现都是flag.jpg是用base64读出来的。
那有没可能读取其他的文件,然后用这种方法将文件直接读出来,再用base64解码呢。现在除了index.php (和flag.txt 脑海里幻想 希望就有这文件而且直接能读吧,打脸了),直接读index.php,发现和之前的一道百度杯很像,但是这里将config 换成了!,
就找到了indexphp的源码了,但是这个和百度杯的那个似乎不一样,怎么试都找不到那个.base文件。就问了下我朋友,他说上面的博客会有提示,whta_the—fuc!!!一开始我还以为是出题人为了宣传自己的博客而放在那里了呢。结果我想多了。
就是这篇文章,说的vim异常退出时产生的文件
这里借一下这位师傅的图
然后就每个都试试,还真的能行。
?>
就读出了这个,这个我记得bugku
也这样的题,就是变量覆盖
这篇文章讲得不错。
2、re
这两道re都是挺基础的,有耐心一点点分析就肯定能出来,一开始以为自己没做个re的题,新手,不敢尝试想留着赛后慢慢复现的,结果就留到了最后一天,结果做到半夜3点。。可怜弱鸡的我
这两道都是差不多题的目,只是壳不同了,之前没脱过壳,后来找了下esp定律,真香。
第一道题 把壳脱完,就出flag,直接跟下去
我没xp,和win7 脱壳失败,师傅说win10有内存保护机制,我就直接鲁了
跟下去
关键call。跟进去
输入code,跟进第一个call
我猜想这个会处理前面输入的数据,也就是code
这个eax就是code是数据长度了
call 完了 栈内的数据
这个就很有意思了。这个怎么来的?
前面有个地方
用eax作为一个index在哪个地址取值,
000F2FF8 0000 add byte ptr ds:[eax],al
000F2FFA 0000 add byte ptr ds:[eax],al000F2FFC 0000 add byte ptr ds:[eax],al000F2FFE 0000 add byte ptr ds:[eax],al000F3000 1BA7 133BE458 sbb esp,dword ptr ds:[edi+0x58E43B13]000F3006 ec in al,dx000F3007 c4ff les edi,edi000F3009 ff db ff000F300A ff db ff000F300B ff db ff000F300C ff db ff000F300D ff db ff000F300E ff db ff000F300F ff db ff000F3010 fe db fe000F3011 ff db ff000F3012 ff db ff000F3013 FF01 inc dword ptr ds:[ecx]000F3015 0000 add byte ptr ds:[eax],al000F3017 007E 7D add byte ptr ds:[esi+0x7D],bh000F301A 7C 7B jl short reverse1.000F3097000F301C 7A 79 jpe short reverse1.000F3097000F301E 78 77 js short reverse1.000F3097000F3020 76 75 jbe short reverse1.000F3097000F3022 74 73 je short reverse1.000F3097000F3024 72 71 jb short reverse1.000F3097000F3026 70 6F jo short reverse1.000F3097000F3028 6e outs dx,byte ptr ds:[esi]000F3029 6d ins dword ptr es:[edi],dx000F302A 6c ins byte ptr es:[edi],dx000F302B 6B6A 69 68 imul ebp,dword ptr ds:[edx+0x69],0x68000F302F 67 addrsize:000F3030 66 datasize:000F3031 65 gs:000F3032 64:6362 61 arpl word ptr fs:[edx+0x61],sp000F3036 60 pushad000F3037 5F pop edi ; reverse1.000F33D4000F3038 5E pop esi000F3039 5D pop ebp000F303A 5C pop esp000F303B 5B pop ebx000F303C 5A pop edx000F303D 59 pop ecx000F303E 58 pop eax000F303F 57 push edi ; reverse1.000F33D4000F3040 56 push esi000F3041 55 push ebp000F3042 54 push esp000F3043 53 push ebx000F3044 52 push edx000F3045 51 push ecx000F3046 50 push eax000F3047 4F dec edi ; reverse1.000F33D4000F3048 4E dec esi000F3049 4D dec ebp000F304A 4c dec esp000F304B 4B dec ebx000F304C 4A dec edx000F304D 49 dec ecx000F304E 48 dec eax000F304F 47 inc edi ; reverse1.000F33D4000F3050 46 inc esi000F3051 45 inc ebp000F3052 44 inc esp000F3053 43 inc ebx000F3054 42 inc edx000F3055 41 inc ecx000F3056 40 inc eax000F3057 3F aas000F3058 3e:3d 3c3b3a39 cmp eax,0x393a3b3c000F305E 3837 cmp byte ptr ds:[edi],dh000F3060 36:35 34333231 xor eax,0x31323334000F3066 302F xor byte ptr ds:[edi],ch000F3068 2e:2d 2c2b2a29 sub eax,0x292a2b2c000F306E 2827 sub byte ptr ds:[edi],ah000F3070 26:25 24232221 and eax,0x21222324000F3076 2000 and byte ptr ds:[eax],al000F3078 0100 add dword ptr ds:[eax],eax000F307A 0000 add byte ptr ds:[eax],al000F307C A8 1B test al,0x1B000F307E 42 inc edx000F307F 0070 10 add byte ptr ds:[eax+0x10],dh000F3082 42 inc edx
就可以看到这些了,而eax呢
通过我们们输入的字符的16进制作为,从0xf2ff8开始找,最后和DDCTF{reverseME}对比一下就ok了,这个就是这道题的解法。
第二道是ASP的壳,一样用esp定律,这里也有像第一道re一样的处理方法,
一样关键call,但是这个call首先判断输入是否合法
012511F0 8BC6 mov eax,esi #esi 指向 字符串012511F2 8D50 01 lea edx,dword ptr ds:[eax+0x1]012511F5 8A08 mov cl,byte ptr ds:[eax]012511F7 40 inc eax012511F8 84C9 test cl,cl012511FA ^ 75 F9 jnz short reverse2.012511F5012511FC 2BC2 sub eax,edx//eax为字符数012511FE 8BD0 mov edx,eax//edx也为字符数01251200 74 39 je short reverse2.0125123B01251202 25 01000080 and eax,0x80000001// eax 为1 就是说eax的最后一位不能为1即 flag的数目为0x1001251207 79 05 jns short reverse2.0125120E01251209 48 dec eax0125120A 83C8 FE or eax,-0x20125120D 40 inc eax0125120E 83F8 01 cmp eax,0x101251211 74 28 je short reverse2.0125123B//就是说eax的最后一位不能为1即 flag的数目为0x1001251213 33C9 xor ecx,ecx01251215 85D2 test edx,edx01251217 7E 1F jle short reverse2.0125123801251219 8DA424 00000000 lea esp,dword ptr ss:[esp]01251220 8A0431 mov al,byte ptr ds:[ecx+esi]01251223 3C 30 cmp al,0x30// 001251225 7C 04 jl short reverse2.0125122B01251227 3C 39 cmp al,0x39//901251229 7E 08 jle short reverse2.012512330125122B 3C 41 cmp al,0x410125122D 7C 0C jl short reverse2.0125123B//全部大于0x410125122F 3C 46 cmp al,0x4601251231 7F 08 jg short reverse2.0125123B//且小于0x46 'F'01251233 41 inc ecx01251234 3BCA cmp ecx,edx01251236 ^ 7C E8 jl short reverse2.0125122001251238 B0 01 mov al,0x10125123A C3 retn0125123B 32C0 xor al,al0125123D C3 retn //0-9 A-F
然后往下走
然后这个就是关键的判断函数了。
0125125F 8D50 01 lea edx,dword ptr ds:[eax+0x1]01251262 8A08 mov cl,byte ptr ds:[eax]01251264 40 inc eax01251265 84C9 test cl,cl01251267 ^ 75 F9 jnz short reverse2.0125126201251269 2BC2 sub eax,edx// eax 就是字符数0125126B 68 FF030000 push 0x3FF01251270 8BF8 mov edi,eax01251272 8D4424 11 lea eax,dword ptr ss:[esp+0x11]01251276 6A 00 push 0x001251278 50 push eax01251279 884C24 18 mov byte ptr ss:[esp+0x18],cl0125127D E8 E8090000 call reverse2.01251C6A ; jmp 到 msvcr90.memset01251282 83C4 0C add esp,0xC01251285 33D2 xor edx,edx01251287 85FF test edi,edi ; msvcr90.printf01251289 7E 61 jle short reverse2.012512EC0125128B 53 push ebx0125128C 8A5C24 0F mov bl,byte ptr ss:[esp+0xF]01251290 8A0416 mov al,byte ptr ds:[esi+edx]01251293 8AC8 mov cl,al01251295 80E9 30 sub cl,0x3001251298 80F9 09 cmp cl,0x9 //跟0x39比(0-9)0125129B 77 06 ja short reverse2.012512A3 如果小与9 就直接把给esp+0xf//大于了就给下面字符的处理0125129D 884C24 0F mov byte ptr ss:[esp+0xF],cl012512A1 EB 10 jmp short reverse2.012512B3012512A3 8AC8 mov cl,al012512A5 80E9 41 sub cl,0x41012512A8 80F9 05 cmp cl,0x5 //(A-F)012512AB 77 06 ja short reverse2.012512B3012512AD 2C 37 sub al,0x37 //不大的话就直接减0x37,然后给esp+0xf012512AF 884424 0F mov byte ptr ss:[esp+0xF],al012512B3 8A4416 01 mov al,byte ptr ds:[esi+edx+0x1] //下一位是否为数字012512B7 8AC8 mov cl,al012512B9 80E9 30 sub cl,0x30012512BC 80F9 09 cmp cl,0x9012512BF 77 04 ja short reverse2.012512C5//如果是数字就将cl给bl,不然就交给下面,下面判断字符012512C1 8AD9 mov bl,cl012512C3 EB 0E jmp short reverse2.012512D3012512C5 8AC8 mov cl,al //是否是字符012512C7 80E9 41 sub cl,0x41012512CA 80F9 05 cmp cl,0x5012512CD 77 04 ja short reverse2.012512D3012512CF 2C 37 sub al,0x37 //如果是字符就将al减去0x37,然后再给bl012512D1 8AD8 mov bl,al上的结论。是数字就直接给bl,字符的渐趋0x37再给bl012512D3 8A4424 0F mov al,byte ptr ss:[esp+0xF]//将esp+0xf的值给al,这里是第一次处理的数据012512D7 C0E0 04 shl al,0x4 //然后al左移四位012512DA 8BCA mov ecx,edx012512DC 0AC3 or al,bl //al or bl ,然后赋予给al012512DE D1E9 shr ecx,1 //ecx右移1位,就相当于除于二012512E0 83C2 02 add edx,0x2 //edx就相当于index012512E3 3BD7 cmp edx,edi edi是字符数 ; msvcr90.printf012512E5 88440C 10 mov byte ptr ss:[esp+ecx+0x10],al012512E9 ^ 7C A5 jl short reverse2.01251290012512EB 5B pop ebx ; msvcr90.printf012512EC 8BC7 mov eax,edi ; msvcr90.printf012512EE 99 cdq// 将eax的32bit 复制到edx的每一个bit上去012512EF 2BC2 sub eax,edx012512F1 D1F8 sar eax,1// eax 除以二012512F3 55 push ebp012512F4 50 push eax012512F5 8D4C24 14 lea ecx,dword ptr ss:[esp+0x14] ecx指向那个前面弄的数组里面就是esp+ecx+0x10012512F9 E8 02FDFFFF call reverse2.01251000012512FE 8B8C24 14040000 mov ecx,dword ptr ss:[esp+0x414]01251305 83C4 08 add esp,0x801251308 5F pop edi ; msvcr90.printf01251309 5D pop ebp ; msvcr90.printf0125130A 33CC xor ecx,esp0125130C E8 4D010000 call reverse2.0125145E01251311 81C4 08040000 add esp,0x40801251317 C3 retn
下面这个是最关键的了。
01251072 8A4424 14 mov al,byte ptr ss:[esp+0x14]#1 第一次调用01251076 8AD0 mov dl,al01251078 C0EA 02 shr dl,0x20125107B 24 03 and al,0x30125107D C0E0 04 shl al,0x401251080 885424 18 mov byte ptr ss:[esp+0x18],dl# 第一次赋值 bl是第二次就是中间的值01251084 8ACB mov cl,bl01251086 C0E9 04 shr cl,0x401251089 02C1 add al,cl0125108B 884424 19 mov byte ptr ss:[esp+0x19],al #第二次赋值0125108F 8A4424 16 mov al,byte ptr ss:[esp+0x16]#2 第san次调用01251093 8AD3 mov dl,bl01251095 80E2 0F and dl,0xF01251098 02D2 add dl,dl0125109A 8AC8 mov cl,al0125109C 02D2 add dl,dl0125109E C0E9 06 shr cl,0x6012510A1 02D1 add dl,cl012510A3 24 3F and al,0x3F012510A5 885424 1A mov byte ptr ss:[esp+0x1A],dl#第三次赋值012510A9 884424 1B mov byte ptr ss:[esp+0x1B],al#第四次赋值012510AD 33F6 xor esi,esi012510AF 90 nop012510B0 0FB65434 18 movzx edx,byte ptr ss:[esp+esi+0x18]012510B5 8A82 20302501 mov al,byte ptr ds:[edx+0x1253020]012510BB 34 76 xor al,0x76012510BD 0FB6C8 movzx ecx,al012510C0 51 push ecx012510C1 8D4C24 24 lea ecx,dword ptr ss:[esp+0x24]//012510F7 8A5C24 21 mov bl,byte ptr ss:[esp+0x21] bl也是AA012510FB 83C4 0C add esp,0xC012510FE 8A4424 14 mov al,byte ptr ss:[esp+0x14] 这里又恢复到0x38指向的位置01251102 8AC8 mov cl,al01251104 8AD3 mov dl,bl01251106 24 03 and al,0x301251108 C0E0 04 shl al,0x40125110B C0EA 04 shr dl,0x40125110E 02C2 add al,dl01251110 C0E9 02 shr cl,0x201251113 80E3 0F and bl,0xF01251116 884424 19 mov byte ptr ss:[esp+0x19],al0125111A 8A4424 16 mov al,byte ptr ss:[esp+0x16]0125111E 02DB add bl,bl01251120 884C24 18 mov byte ptr ss:[esp+0x18],cl01251124 8AC8 mov cl,al01251126 02DB add bl,bl01251128 C0E9 06 shr cl,0x60125112B 02D9 add bl,cl0125112D 885C24 1A mov byte ptr ss:[esp+0x1A],bl01251131 24 3F and al,0x3F01251133 8D5E 01 lea ebx,dword ptr ds:[esi+0x1]01251136 33FF xor edi,edi01251138 884424 1B mov byte ptr ss:[esp+0x1B],al0125113C 85DB test ebx,ebx0125113E 7E 20 jle short reverse2.0125116001251140 0FB6543C 18 movzx edx,byte ptr ss:[esp+edi+0x18]01251145 8A82 20302501 mov al,byte ptr ds:[edx+0x1253020]0125114B 34 76 xor al,0x760125114D 0FB6C8 movzx ecx,al01251150 51 push ecx01251151 8D4C24 24 lea ecx,dword ptr ss:[esp+0x24]
就是这个搞了我好几个小时,
关键的就是
这就个add ,这里通过前面的几个运算,然后四个bit一起,往栈写8个bit 这8个bit是用前面算好的 放在[esp + 0x14] 到[esp +0x 16] 的这个值,然后通运算在
01253014 0100 add dword ptr ds:[eax],eax01253016 0000 add byte ptr ds:[eax],al01253018 14 21 adc al,0x210125301A 25 01000000 and eax,0x10125301F 0037 add byte ptr ds:[edi],dh01253021 34 35 xor al,0x3501253023 3233 xor dh,byte ptr ds:[ebx]01253025 3031 xor byte ptr ds:[ecx],dh01253027 3e:3f aas01253029 3C 3D cmp al,0x3D0125302B 3A3B cmp bh,byte ptr ds:[ebx]0125302D 3839 cmp byte ptr ds:[ecx],bh0125302F 26:27 daa01253031 24 25 and al,0x2501253033 2223 and ah,byte ptr ds:[ebx]01253035 2021 and byte ptr ds:[ecx],ah01253037 2e:2f das01253039 2C 17 sub al,0x170125303B 14 15 adc al,0x150125303D 1213 adc dl,byte ptr ds:[ebx]0125303F 1011 adc byte ptr ds:[ecx],dl01253041 1E push ds01253042 1f pop ds01253043 1C 1D sbb al,0x1D01253045 1A1B sbb bl,byte ptr ds:[ebx]01253047 1819 sbb byte ptr ds:[ecx],bl01253049 06 push es0125304A 07 pop es0125304B 04 05 add al,0x50125304D 0203 add al,byte ptr ds:[ebx]0125304F 0001 add byte ptr ds:[ecx],al01253051 0E push cs01253052 0f db 0f01253053 0C 46 or al,0x4601253055 47 inc edi01253056 44 inc esp01253057 45 inc ebp //01253058 42 inc edx01253059 43 inc ebx0125305A 40 inc eax0125305B 41 inc ecx0125305C 4E dec esi0125305D 4F dec edi0125305E 5D pop ebp0125305F 59 pop ecx01253060 0100 add dword ptr ds:[eax],eax01253062 0000 add byte ptr ds:[eax],al01253064 A8 1B test al,0x1B01253066 B6 00 mov dh,0x001253068 70 10 jo short reverse2.0125307A0125306A B6 00 mov dh,0x0
这个表里面找出数据最后和0x76 XOR 最后结果是 DDCTF{reverse+}括号里面的内容就ok,前面也有个地方判断,字符串的长度的最后一位不能是1,还有要满足6的倍数,不然最后一个会加上'=' 这就不可能匹配了。
经过了这次的比赛后,发现re还是得多练,一步不跟进,慢慢分析里面的算法,小心出题的人留下的坑。。。。。
有哪里写的不对的请大家多多包涵,可以的希望能给我指出来。