看雪CTF.TSRC 2018 团队赛 第十二题 移动迷宫
程序运行会在临时目录释放dll出来,并加载执行,加载和执行位置:
.text:0040203A push 8 ; dwFlags
.text:0040203C push ebx ; hFile
.text:0040203D push esi ; lpLibFileName
.text:0040203E call ds:LoadLibraryExA
.text:00402044 mov edi, eax
.text:00402046 cmp edi, ebx
.text:00402048 jz short loc_4020C3
.text:0040204A push [ebp+FilePart] ; lpProcName
.text:0040204D push edi ; hModule
.text:0040204E call GetProcAddress
.text:00402053 mov esi, eax
.text:00402055 cmp esi, ebx
.text:00402057 jz short loc_402096
.text:00402059 cmp [ebp+dwBytes], ebx
.text:0040205C mov [ebp+var_4], ebx
.text:0040205F jz short loc_402078
.text:00402061 push [ebp+dwBytes]
.text:00402064 call sub_401423
.text:00402069 call esi
.text:0040206B test eax, eax
.text:0040206D jz short loc_4020A0
.text:0040206F mov [ebp+var_4], 1
.text:00402076 jmp short loc_4020A0
.text:00402078 push offset off_40A000
.text:0040207D push offset hMem
.text:00402082 push offset byte_430000
.text:00402087 push 400h
.text:0040208C push [ebp+hWnd]
.text:0040208F call esi
.text:00402091 add esp, 14h
.text:00402094 jmp short loc_4020A0
有下面这几个dll:
nsDialogs.dll
KillProcDLL.dll //有程序检测,会杀掉它不喜欢的进程
System.dll //间接调用系统api
Bamer.dll //主要算法部分
Bamer.dll有几个导出函数:
Bamer.P //输入字符有效性检查
Bamer.B //修改过的base64解码
Bamer.A //修改过的aes解密
Bamer.C //36进制转4进制
Bamer.G //一个12*12的路径寻找游戏,8对点,在格子内连成8条线,互不交叉,格子必须要全部用完
Bamer.F //最后的hash校验
主程序内嵌一个解释器,指令数不多:
.text:00401ABB mov eax, [ebp+FileTime2.dwLowDateTime]
.text:00401ABE cmp eax, 0Dh ; switch 14 cases
.text:00401AC1 ja short loc_401B36 ; jumptable 00401AC3 default case
.text:00401AC3 jmp ds:off_402A71[eax*4] ; switch jump
.text:00401ACA loc_401ACA: ; CODE XREF: sub_401434+68F↑j
.text:00401ACA add edi, ecx ; 加法
.text:00401ACC jmp short loc_401B39
.text:00401ACE loc_401ACE: ; CODE XREF: sub_401434+68F↑j
.text:00401ACE sub edi, ecx ; 减法
.text:00401AD0 jmp short loc_401B39
.text:00401AD2 loc_401AD2: ; CODE XREF: sub_401434+68F↑j
.text:00401AD2 imul ecx, edi ; 乘法
.text:00401AD5 jmp short loc_401AEE
...
.text:00401AEC loc_401AEC: ; CODE XREF: sub_401434+68F↑j
.text:00401AEC xor ecx, edi ; 异或
.text:00401AEE mov edi, ecx
.text:00401AF0 jmp short loc_401B39
这里可以监视到数值比较:
.text:00401A84 cmp edi, eax
这里可以监视到字符串比较:
.text:00401A16 call ds:lstrcmpA
有了前面这些加减乘异或和两处比较的监视点结合硬件断点,就可以跟踪出验证逻辑了
输入长度要求100个字符,经Bamer.B的base64解码后得到75个字节
取出前11个字节,xor 0x17再减去位置索引值,得到的结果与固定串{25,26,24,2C,3F,3F,4E,3E,4C,3A,47}比较
解出得到:2018TSCRCTF
这样算完成第一部分验证
然后剩下的64字节,用前面得到的结果再拼接一部分得到的2018TSCRCTF00010做为密钥,经Bamer.A的aes解密
取出前11字节,然后又是经过解释器处理循环,追踪记录整理后得到这样一个十一元一次方程组:
a[0] * 19292 + a[1] * 21770 + a[2] * 17677 - a[3] * 18327 + a[4] * 19344 + a[5] * 16593 - a[6] * 20094 + a[7] * 20472 - a[8] * 19029 + a[9] * 16001 - a[10] * 20980 = 5295553
a[0] * 17901 + a[1] * 17754 + a[2] * 22962 - a[3] * 24365 - a[4] * 20645 - a[5] * 20553 + a[6] * 21906 + a[7] * 24749 + a[8] * 20195 + a[9] * 20968 - a[10] * 17780 = 5518223
a[0] * 23630 - a[1] * 23633 - a[2] * 18077 + a[3] * 15076 - a[4] * 17525 - a[5] * 15510 + a[6] * 24396 + a[7] * 24273 + a[8] * 24865 + a[9] * 22272 + a[10] * 18068 = 6649741
a[0] * 17723 + a[1] * 22504 - a[2] * 22913 + a[3] * 21286 + a[4] * 16384 + a[5] * 15349 - a[6] * 22234 - a[7] * 23057 + a[8] * 17180 - a[9] * 20872 + a[10] * 22229 = 4482135
a[0] * 18536 + a[1] * 18849 - a[2] * 19901 - a[3] * 18443 + a[4] * 15180 - a[5] * 23787 + a[6] * 23788 - a[7] * 15487 + a[8] * 16571 + a[9] * 15420 + a[10] * 17695 = 5135079
a[0] * 20282 + a[1] * 21583 + a[2] * 18830 + a[3] * 24997 + a[4] * 17723 - a[5] * 24278 - a[6] * 22517 + a[7] * 20548 + a[8] * 24963 - a[9] * 19274 - a[10] * 18086 = 5299343
a[0] * 22035 + a[1] * 23475 - a[2] * 16349 + a[3] * 18849 + a[4] * 22560 - a[5] * 19397 + a[6] * 21857 + a[7] * 23641 - a[8] * 15110 + a[9] * 21024 + a[10] * 21705 = 11895342
a[0] * 18334 + a[1] * 19371 - a[2] * 17784 + a[3] * 21534 - a[4] * 23633 + a[5] * 16027 - a[6] * 18430 - a[7] * 24544 + a[8] * 16158 + a[9] * 15917 + a[10] * 18278 = 4549415
a[0] * 20198 + a[1] * 22945 + a[2] * 23807 - a[3] * 17050 - a[4] * 21682 + a[5] * 16136 + a[6] * 23014 + a[7] * 19532 - a[8] * 19020 - a[9] * 23750 + a[10] * 19323 = 5344900
a[0] * 18800 - a[1] * 15632 + a[2] * 23898 + a[3] * 22359 + a[4] * 20855 + a[5] * 16366 - a[6] * 15562 + a[7] * 21845 + a[8] * 21734 + a[9] * 21130 + a[10] * 20089 = 15581697
a[0] * 17297 + a[1] * 20004 + a[2] * 20329 - a[3] * 24185 - a[4] * 24637 - a[5] * 15223 - a[6] * 19192 - a[7] * 23539 + a[8] * 23170 + a[9] * 17101 + a[10] * 16781 = 1259535
解出得到:
[87,101,108,99,111,109,101,72,97,118,101]
对应的字符串是:WelcomeHave
到这里算完成第二部分验证
把剩下的53个字节通过Bamer.C从36进制转成4进制做为参数传给Bamer.G
再把上面得到的结果拆分拼接得到WelcomeToHaveFun做为密钥,通过aes解密Bamer.dll中一段固定数据得到一个12*12的图案:
...........B
.R...Y..A...
............
.....DG..R..
............
......B.S...
............
.......D....
.......P....
......Y.....
.......G..S.
.....P...A..
图案中ABDGPRSY8个字符成对,在sub_100021DA中会用先前的4进制数据做为上下左右操作码,在图中画线路,下图是我手动画出的解法(小写字母表示一对大写字母之间的连线):
pppppppbbbbB
pRyyyYpbAaaa
pryppppbsssa
prypdDGbsRsa
prypdggbsrsa
prypdgBbSrsa
prypdggggrsa
prypdddDgrsa
pryppppPgrsa
pryyyyYggrsa
prrrrrrGrrSa
pppppPrrrAaa
8条线操作步骤(起点是行号小的一点,左0右1上2下3):
A:111333333333300
B:0000333330
D:03333111
G:303311133303
P:0000222222111220000003333333333311111
R:33333333311111311212222222
S:2221133333333
Y:000333333331111
最后可以构造flag了,8条线拼接在一起得到:
1113333333333000000333330033331113033111333030000222222111220000003333333333311111333333333111113112122222222221133333333000333333331111
4进制转成36进制得到53字节:
32WSFUPIFV9TYJWWPH14NZZ85YDHXOLO37ATG4IYC4ZCDIKCA7EJ9
前面拼接第二部分的11字节WelcomeHave得到64字节:
WelcomeHave32WSFUPIFV9TYJWWPH14NZZ85YDHXOLO37ATG4IYC4ZCDIKCA7EJ9
aes加密后再拼接第一部分11字节,然后变种base64编码得到100个字符的最终结果:
MhAyOFQSR2JDUEb0OUopUQkh5Ax23nEnCLxoBT06JRd7EdLrwooWsXQG68wLcneAqDy3UU78AgdrYnabVL0M9vd852girNqF9a3F