-
-
[原创][2020][KCTF] 第七题 杯弓蛇影 wp
-
2020-4-28 11:10 4844
-
一 壳部分
有些anti,最主要的是GetThreadContext,会检查drx是否为0:
0044F244 FFD1 CALL ECX //GetThreadContext 0044F246 C745 F8 00000000 MOV DWORD PTR SS:[EBP-8],0 0044F24D 83BD 30FDFFFF 00 CMP DWORD PTR SS:[EBP-2D0],0 //dr0 == 0 ? 0044F254 75 1B JNZ SHORT CrackMe.0044F271 0044F256 83BD 34FDFFFF 00 CMP DWORD PTR SS:[EBP-2CC],0 //dr1 == 0 ? 0044F25D 75 12 JNZ SHORT CrackMe.0044F271 0044F25F 83BD 38FDFFFF 00 CMP DWORD PTR SS:[EBP-2C8],0 //dr2 == 0 ? 0044F266 75 09 JNZ SHORT CrackMe.0044F271 0044F268 83BD 3CFDFFFF 00 CMP DWORD PTR SS:[EBP-2C4],0 //dr3 == 0 ? 0044F26F 74 07 JE SHORT CrackMe.0044F278 00450E97 E8 24FDFFFF CALL CrackMe.00450BC0 //处理输入表,可以在这里dump 00450E9C 83C4 10 ADD ESP,10 00450E9F 8945 D0 MOV DWORD PTR SS:[EBP-30],EAX 00450EA2 837D D0 00 CMP DWORD PTR SS:[EBP-30],0 00450EA6 75 04 JNZ SHORT CrackMe.00450EAC 00450EA8 33C0 XOR EAX,EAX 00450EAA EB 1E JMP SHORT CrackMe.00450ECA 00450EAC 8B4D 08 MOV ECX,DWORD PTR SS:[EBP+8] 00450EAF 51 PUSH ECX 00450EB0 E8 4BE3FFFF CALL CrackMe.0044F200 00450EB5 83C4 04 ADD ESP,4 00450EB8 83F8 01 CMP EAX,1 00450EBB 75 05 JNZ SHORT CrackMe.00450EC2 00450EBD E8 1EE3FFFF CALL CrackMe.0044F1E0 00450EC2 FF55 F0 CALL DWORD PTR SS:[EBP-10] //to oep : 0x417E83 00450CE3 8B55 08 MOV EDX,DWORD PTR SS:[EBP+8] 00450CE6 52 PUSH EDX 00450CE7 8B45 F0 MOV EAX,DWORD PTR SS:[EBP-10] 00450CEA 50 PUSH EAX 00450CEB E8 60F3FFFF CALL CrackMe.00450050 //可以nop掉,阻止函数入口抽取 00450CF0 83C4 08 ADD ESP,8 00450CF3 8945 EC MOV DWORD PTR SS:[EBP-14],EAX
二 验证流程:
004011A7 68 685A4300 PUSH CrackMe.00435A68 //"Please input Serial:" 004011AC E8 BFFEFFFF CALL CrackMe.00401070 004011B1 83C4 04 ADD ESP,4 004011B4 8D8424 E00C0000 LEA EAX,DWORD PTR SS:[ESP+CE0] 004011BB 68 E8030000 PUSH 3E8 004011C0 50 PUSH EAX 004011C1 68 645A4300 PUSH CrackMe.00435A64 004011C6 E8 E5FEFFFF CALL CrackMe.004010B0 //读取sn 。。。 0040157A 8B4424 18 MOV EAX,DWORD PTR SS:[ESP+18] 0040157E 8D4C24 60 LEA ECX,DWORD PTR SS:[ESP+60] 00401582 898424 D0000000 MOV DWORD PTR SS:[ESP+D0],EAX //0044B258,大端转换后的sn 00401589 8B4424 14 MOV EAX,DWORD PTR SS:[ESP+14] 0040158D 898424 D4000000 MOV DWORD PTR SS:[ESP+D4],EAX 00401594 8B4424 10 MOV EAX,DWORD PTR SS:[ESP+10] 00401598 898424 D8000000 MOV DWORD PTR SS:[ESP+D8],EAX //0044BE58,输入参数 0040159F 8B4424 1C MOV EAX,DWORD PTR SS:[ESP+1C] 004015A3 898424 DC000000 MOV DWORD PTR SS:[ESP+DC],EAX 004015AA 8B4424 20 MOV EAX,DWORD PTR SS:[ESP+20] 004015AE 898424 E0000000 MOV DWORD PTR SS:[ESP+E0],EAX //00448358,输入参数 004015B5 8B4424 24 MOV EAX,DWORD PTR SS:[ESP+24] 004015B9 898424 E4000000 MOV DWORD PTR SS:[ESP+E4],EAX 004015C0 8B4424 28 MOV EAX,DWORD PTR SS:[ESP+28] 004015C4 898424 E8000000 MOV DWORD PTR SS:[ESP+E8],EAX //0044B658,输出5个DWORD 004015CB 8B4424 2C MOV EAX,DWORD PTR SS:[ESP+2C] 004015CF 898424 EC000000 MOV DWORD PTR SS:[ESP+EC],EAX 004015D6 8B4424 30 MOV EAX,DWORD PTR SS:[ESP+30] 004015DA 898424 F8000000 MOV DWORD PTR SS:[ESP+F8],EAX //00448338,输出8个DWORD 004015E1 8B4424 34 MOV EAX,DWORD PTR SS:[ESP+34] 004015E5 898424 FC000000 MOV DWORD PTR SS:[ESP+FC],EAX 004015EC E8 3FCB0000 CALL CrackMe.0040E130 //应该是个虚拟机 。。。 经过一番调试观察,找到下面几个关键的运算位置: 0040F47C E8 CFF20100 CALL CrackMe.0042E750 //vm_mul 0040F512 E8 790D0000 CALL CrackMe.00410290 //vm_div,这里面有anti 0040F3C0 E8 1B0D0000 CALL CrackMe.004100E0 //vm_add,这里面有anti 0040F6BD 3144D3 68 XOR DWORD PTR DS:[EBX+EDX*8+68],EAX //vm_xor 输入公开的一组用户名和序列号,利用上面4个断点观察数值的变化: s = 0 m = 0xFFFFFFFB b = 1 s = (0x45CEB196 * b % m + s) % m = 0x45CEB196 b = b * 0x158EA2A9 % m = 0x158EA2A9 s = (0xA20DD51E * b % m + s) % m = 0xF2AC7FFF b = b * 0x158EA2A9 % m = 0x9DE9E259 s = (0xEAADB7F2 * b % m + s) % m = 0x8E85CE47 b = b * 0x158EA2A9 % m = 0x5D7D98F0 0x4B82D0BC ^ 0x8E85CE47 = 0xC5071EFB 从虚拟机出来以后,观察输入输出可以得出: 0x158EA2A9是输入参数[44BE58]的第一个DWORD 0x4B82D0BC是输入参数[448358]的第一个DWORD 0x45CEB196,0xA20DD51E,0xEAADB7F2刚好是输入sn即[44B258]的前三个DWORD [44B658]输出了5个DWORD,[448338]输出8个DWORD,加起来13个DWORD,输入sn三个一组的话刚好也是13组 0xC5071EFB是输出[44B658]的第一个DWORD 单从一个输出可以猜测出: out[i] = (sn[3*i+0] + sn[3*i+1] * DWORD_44BE58[i] + sn[3*i+2] * DWORD_44BE58[i] * DWORD_44BE58[i]) % m ^ DWORD_448358[i] 经验证验证后面12组也符合此规律,至此vm里的算法就算猜出来了 后续验证流程: 00401600 8BC8 MOV ECX,EAX 00401602 83E1 07 AND ECX,7 00401605 8B148D 38834400 MOV EDX,DWORD PTR DS:[ECX*4+448338] //输出后8个DWORD 0040160C 331485 58B64400 XOR EDX,DWORD PTR DS:[EAX*4+44B658] //输出前5个DWORD 00401613 8BCA MOV ECX,EDX 00401615 891485 78BE4400 MOV DWORD PTR DS:[EAX*4+44BE78],EDX 0040161C C1E9 08 SHR ECX,8 0040161F 880C85 7AC24400 MOV BYTE PTR DS:[EAX*4+44C27A],CL 00401626 8BCA MOV ECX,EDX 00401628 881485 7BC24400 MOV BYTE PTR DS:[EAX*4+44C27B],DL 0040162F C1E9 10 SHR ECX,10 00401632 C1EA 18 SHR EDX,18 00401635 880C85 79C24400 MOV BYTE PTR DS:[EAX*4+44C279],CL 0040163C 881485 78C24400 MOV BYTE PTR DS:[EAX*4+44C278],DL //xor后再大小端转换,得到一个人为设定的字符串,三轮的结果不同 00401643 40 INC EAX 00401644 3BC6 CMP EAX,ESI 00401646 ^7C B8 JL SHORT CrackMe.00401600 00401648 FF7424 38 PUSH DWORD PTR SS:[ESP+38] 0040164C BA 38B24400 MOV EDX,CrackMe.0044B238 //hash输出 00401651 B9 78C24400 MOV ECX,CrackMe.0044C278 //设定的字符串 00401656 FF7424 40 PUSH DWORD PTR SS:[ESP+40] 0040165A E8 11C00000 CALL CrackMe.0040D670 //感觉是个hash,也不知道哪种hash,还带vm,咱就不和它较劲了,直接看输出结果 0040165F 83C4 08 ADD ESP,8 00401662 33C9 XOR ECX,ECX 00401670 8B81 38834400 MOV EAX,DWORD PTR DS:[ECX+448338] //输出后8个DWORD 00401676 3B81 38B24400 CMP EAX,DWORD PTR DS:[ECX+44B238] //hash 0040167C 75 3F JNZ SHORT CrackMe.004016BD //输出前5个DWORD与后8个DWORD异或得到字符串的hash == 输出后8个DWORD ? 0040167E 83C1 04 ADD ECX,4 00401681 83F9 20 CMP ECX,20 00401684 ^7C EA JL SHORT CrackMe.00401670 00401686 8B4424 7C MOV EAX,DWORD PTR SS:[ESP+7C] 0040168A 85C0 TEST EAX,EAX 0040168C 74 09 JE SHORT CrackMe.00401697 0040168E 50 PUSH EAX 0040168F E8 9A650100 CALL CrackMe.00417C2E 00401694 83C4 04 ADD ESP,4 00401697 8B4424 08 MOV EAX,DWORD PTR SS:[ESP+8] 0040169B 83C7 04 ADD EDI,4 0040169E 05 00010000 ADD EAX,100 004016A3 894424 08 MOV DWORD PTR SS:[ESP+8],EAX 004016A7 81FF 64BA4400 CMP EDI,CrackMe.0044BA64 //循环三轮 004016AD ^0F8C FDFDFFFF JL CrackMe.004014B0 004016B3 68 A45A4300 PUSH CrackMe.00435AA4 ; ASCII "Congratulations! The Serial is Correct!" 004016B8 ^E9 59FCFFFF JMP CrackMe.00401316 只要使vm输出的[44B658]和[448338]一共13个DWORD和公开那组用户名/序列号的结果一样,后面hash就都会自然通过验证 DWORD_448358内容是和用户名相关的,DWORD_44BE58是和用户名和轮次相关的 vm跑了三轮,vm前面分析出的算法可以建立一个三元一次同余方程组: out[i] = (sn[3*i+0] + sn[3*i+1] * DWORD_44BE58[i] + sn[3*i+2] * DWORD_44BE58[i] * DWORD_44BE58[i]) % m ^ DWORD_448358[i] 输入用户名KCTF把每轮的[448358]和[44BE58]都抓取出来得到系数矩阵,解13个方程组,得到全部13个DWORD即可
三 解方程的sage代码:
base_44BE58_pub = [ [0x158EA2A9,0x0119F92D,0xA8E297DF,0x114EFFC3,0x3D192BAC,0xD1354A27,0xBE4D0722,0x365DF0C9], [0xBCB9C89C,0x1AC6837F,0xB72DD1BF,0xC41AFC16,0xE1C33972,0x3998A0AE,0xBBDE5E70,0xA09E23E0], [0xF1E0C866,0xC69DE660,0x4CB62BA8,0x4E0DCD2F,0xA1DC0564,0xE8DB2CCF,0xD10A0F17,0xCDD12459] ] key_448358_pub = [0x4B82D0BC,0xF8B8853D,0x049D762A,0x362AD93C,0xB49B3DE9,0xE2D166BC,0xCF1EE01B,0xD4E36847,0xB40A13BE,0xE536D6B8,0xDECBDD5E,0xBDE27342,0xD2EF4FBD] base_44BE58_KCTF = [ [0x835904E1,0xC834944B,0x027A19E0,0xFEB308A3,0x621FF195,0x4B705C5C,0x3EB5D9D0,0x9A5C73F4], [0xCCFFA00F,0x490C46ED,0xF78BE5A1,0x81A56274,0x165DEB5C,0xF6F46796,0x44DE5146,0x00E4984C], [0xDF77DFA8,0xAE0ED8D8,0x064DA354,0x4C8B95CC,0xF934CA39,0xC4E9DE04,0x18EE2793,0x945AC9C2], ] key_448358_KCTF = [0xD9C3E463,0x11C9AF78,0x6485BF9E,0xFF4BD05D,0x65769726,0xF5C38988,0xBF3A2423,0x4B718CC0,0xC70D8F49,0xDFC73315,0x74470070,0x94B89F71,0x0E60F6B1] sn_pub = [0x45CEB196,0xA20DD51E,0xEAADB7F2,0x17A4AABF,0x036D8FE4,0x81DAFC12,0x6C310213,0x7691C395,0x27444D11,0x0E0D1071,0x99703FD6,0xAAA510DF,0xE8433E09,0x702603E8,0x10A68ED0,0x06082EF6,0xF2793580,0x2B2CE24F,0x105F91CA,0xDF697948,0x92B4F088,0x4DADF6A7,0x0A1F25BD,0x23A2D4D2,0xE36D836F,0xE9946B9F,0x559D26C6,0x3237E615,0xE218F66B,0x6A572CF3,0xBDA45BD8,0x8D0E7E59,0xB9C93D8F,0xA55B218D,0x3643F639,0x0C6AA85F,0x2B8EB982,0x18F4C6C9,0x4E17CC73] t = [] p = 0xFFFFFFFB for i in range(13): c = [] for j in range(3): a = [] b = 1 a.append(b) b = b * base_44BE58_pub[j][i%8] % p a.append(b) b = (b * base_44BE58_pub[j][i%8]) % p a.append(b) y = (a[0] * sn_pub[i*3+0] + a[1] * sn_pub[i*3+1] + a[2] * sn_pub[i*3+2]) % p a.append(y ^^ key_448358_pub[i]) b = 1 a[0] = b b = b * base_44BE58_KCTF[j][i%8] % p a[1] = b b = (b * base_44BE58_KCTF[j][i%8]) % p a[2] = b a[3] ^^= key_448358_KCTF[i] c += a t.append(c) A = matrix(Zmod(p), 3, 3) for i in range(13): for j in range(3): A[j] = [t[i][j*4+0],t[i][j*4+1],t[i][j*4+2]] B = vector(Zmod(p),[t[i][0*4+3],t[i][1*4+3],t[i][2*4+3]]) x = A\B print('%08X%08X%08X' % (x[0],x[1],x[2]))
运行后得到结果:E84DE727B4C7223FC4C8B34F9D4E4221225DD4A26A95E624E5EB45269DE64C0A9ED50B44BBA723F9878E4B4DD8841263453DC5157B401D6B5AF4F1401193FAA1433ADA48145A358ABCE1B8439C7F5D390C31987E39BB056E1A21B92B8DE2358ECEC1FF6C206CF8C17C46C89144BA8DA0EC4834389FFA54B32C8D3174E97AC3C2024783D0DFDC2BC9524B9C81B40F78F2E184A49B2292B4D79A58EF0B
[CTF入门培训]顶尖高校博士及硕士团队亲授《30小时教你玩转CTF》,视频+靶场+题目!助力进入CTF世界
最后于 2020-4-28 16:19
被ccfer编辑
,原因:
赞赏
他的文章
看原图