某国赛CTF逆向题目Writeup:re2
目录脱壳第一层EXE第二层EXEFLAG脱壳010打开UPX改了特征码版本5.1.0直接拖到ida分析不出来这里我们选择动态调试脱壳先找OEPf9运行到入口触发TLS回调函数断点停在了ret上64位UPX壳中不会用一个明显的跨段jmp指令跳向OEP而是把OEP的地址压入堆栈然后执行一条ret指令这样CPU就会把堆栈顶部的OEP地址当作返回地址弹出来并跳转过去我们直接f8过去此时进入了系统DLL地址不用管执行到用户代码标准的UPX壳保存环境的方式步过4次此时当前的栈顶已经被修改了内存中转到RSP在栈顶位置下硬件断点然后一直f9到触发硬件断点此时正在恢复保存的寄存器状态最后的jmp即是尾部跳转直接f4过去然后步过一下可以看到已经解密完成0x4014E0就是OEP打开Scylla插件搜索IAT找到两个IAT大小因为这个exe只有几十kb528字节的输入表正好选择否然后获取输入表dump之后修复得到最终脱壳后的程序第一层EXE通过ida逆向可以看到这里是获取了用户的输入并和Str2进行比较Str 为 NGeQwv8eCRpINEcO标准的windows可执行文件头如果正确就会通过sub_401660函数进行base64解码并向缓存路径内写入一个随机名称的exe直接执行原文件输入密码就能得到第二层EXE运行发现需要输入key继续通过ida逆向这个文件通过main函数找到处理逻辑sub_401550函数分析可知这里的逻辑也是接收用户输入的key然后通过nullsub_3函数判断key是否正确中间的do-while步骤是优化后的strlen函数实现输入长度不超过240现在我们的思路就是分析nullsub_3函数不过nullsub在ida中代表为只有一个ret的空函数说明针对反编译器做了修改我们需要看看到底是不是真的空函数跟进后发现是一个奇怪的hello节应该就是题目提示了这里我们选择通过x64dbg进行动态调试首先加载后找到主逻辑函数地址查找Enter the key关键字引用ida中找到地址输出Faild和Success中间的call就是直接跳转然后下断点0x401623然后一直f9运行到等待用户输入返回窗口随便输入一串key12345678跟进这里可以看到明显是有内容的分析逻辑如下1、逐字节读取刚刚输入的key2、计算离16字节的填充并补齐经典的PKCS#7填充3、为404CB0函数准备参数rcx、r9、r8基本可以判断是AES或者SM4运行到404F86调用404CB0函数之前拿到三个参数Key: C2 30 12 AB 39 10 18 33 F8 ED 4E 46 8D A1 5D 8D 8C FB F0 72 68 99 DC 7C 84 6E 7E CF 32 BB DA F8 IV: AE BA 0D BB CA 26 7F 99 06 ED 7C 70 E3 8D 8B 11 CipherText: 9B 5E 1E 8F D7 C3 43 62 A2 37 86 C0 CE 3D 3C F4 C3 B6 88 FF 3C 9C 13 D2 BB 6F 49 CE FF 59 A2 5C 36 E4 61 9E 60 61 C3 BB 3F 63 AF 00 3B 3D 8D A7然而AES和SM4解密都失败了说明题目对标准加密流程进行了魔改跟进404CB0函数内部这里往栈上压入了一个参数E十进制14而加密轮数14的分组密码只有AES我们上一步解密失败了最大的可能就是魔改了标准的S盒往下看压栈后调用了404B60函数直接跟进这里就是AES的核心算法先把内存地址 4071E0 装载到了 r14 寄存器里然后把明文字节当做索引 rdx去 r14 也就是 4071E0 这个地址里查表替换这就是 AES 加密中最核心的字节替换操作那么4071E0地址就是魔改S盒的地址然而进去后发现就是标准的S盒接下来就该排查行移位ShiftRows和列混淆MixColumns步骤有没有问题这里调用了2个函数分别跟进看一下4040700, 5, 10, 15、13, 4, 9, 14、8, 13, 2, 7正确对应行移位后的矩阵排列4041900x1B 是 AES 有限域乘法的标准多项式常数2 和 3 也是标准的乘法矩阵到这里我们总结一下1、标准S盒2、标准行移位3、标准列混淆还剩最后一个密钥扩展算法这里我们想要重新分析算法就比较复杂了但是最终是要生成好放进内存直接在密钥生成器之后在内存中获取即可重新运行跟进到404B60内部在字节替换操作之前调用了一个404940函数多半就是轮密钥的生成逻辑运行到此处步过一次而生成的轮密钥随后就被存放在了rbx寄存器指向的地址内存窗口中找到正好240字节C2 30 12 AB 39 10 18 33 F8 ED 4E 46 8D A1 5D 8D 8C FB F0 72 68 99 DC 7C 84 6E 7E CF 32 BB DA F8 B4 67 53 88 8D 77 4B BB 75 9A 05 FD F8 3B 58 70 CD 19 9A 23 A5 80 46 5F 21 EE 38 90 13 55 E2 68 58 FF 16 F5 D5 88 5D 4E A0 12 58 B3 58 29 00 C3 A7 BC F9 0D 02 3C BF 52 23 D2 87 C2 30 87 65 AA 5C B2 BA F1 89 3A E7 BF 29 28 BF 0C 71 01 BF CF 04 C0 F1 87 06 FC 4E D5 25 2E C9 17 15 A9 AC BD 9A 23 C0 A8 13 19 27 17 3A 31 98 1B 4B 30 27 D4 B7 C4 3D CF B1 38 73 1A 94 16 BA 0D 81 BF 16 B0 8B 64 27 A4 98 7D 00 B3 A2 4C 98 A8 E9 7C BF 7C A9 D4 35 DF 18 EC 46 C5 8C FA FC C8 0D 45 EA 78 E4 E3 9B 73 7C 9E 9B C0 DE D2 03 68 37 AE BC 14 33 30 50 25 2B DC 16 E0 A7 26 EA 28 AA 63 00 50 2E 80 C8 DF 52 1E 53 1F 8C CC 50 77 BB 62 EC 63编写自定义轮密钥的解密脚本# 自定义的轮密钥expanded_key_hexC2 30 12 AB 39 10 18 33 F8 ED 4E 46 8D A1 5D 8D 8C FB F0 72 68 99 DC 7C 84 6E 7E CF 32 BB DA F8 B4 67 53 88 8D 77 4B BB 75 9A 05 FD F8 3B 58 70 CD 19 9A 23 A5 80 46 5F 21 EE 38 90 13 55 E2 68 58 FF 16 F5 D5 88 5D 4E A0 12 58 B3 58 29 00 C3 A7 BC F9 0D 02 3C BF 52 23 D2 87 C2 30 87 65 AA 5C B2 BA F1 89 3A E7 BF 29 28 BF 0C 71 01 BF CF 04 C0 F1 87 06 FC 4E D5 25 2E C9 17 15 A9 AC BD 9A 23 C0 A8 13 19 27 17 3A 31 98 1B 4B 30 27 D4 B7 C4 3D CF B1 38 73 1A 94 16 BA 0D 81 BF 16 B0 8B 64 27 A4 98 7D 00 B3 A2 4C 98 A8 E9 7C BF 7C A9 D4 35 DF 18 EC 46 C5 8C FA FC C8 0D 45 EA 78 E4 E3 9B 73 7C 9E 9B C0 DE D2 03 68 37 AE BC 14 33 30 50 25 2B DC 16 E0 A7 26 EA 28 AA 63 00 50 2E 80 C8 DF 52 1E 53 1F 8C CC 50 77 BB 62 EC 63.replace( ,)ivbytes.fromhex(AEBA0DBBCA267F9906ED7C70E38D8B11)ctbytes.fromhex(9B5E1E8FD7C34362A23786C0CE3D3CF4C3B688FF3C9C13D2BB6F49CEFF59A25C36E4619E6061C3BB3F63AF003B3D8DA7)expanded_keybytes.fromhex(expanded_key_hex)round_keys[list(expanded_key[i:i16])foriinrange(0,240,16)]# 标准S盒、逆S盒SBOX[0x63,0x7C,0x77,0x7B,0xF2,0x6B,0x6F,0xC5,0x30,0x01,0x67,0x2B,0xFE,0xD7,0xAB,0x76,0xCA,0x82,0xC9,0x7D,0xFA,0x59,0x47,0xF0,0xAD,0xD4,0xA2,0xAF,0x9C,0xA4,0x72,0xC0,0xB7,0xFD,0x93,0x26,0x36,0x3F,0xF7,0xCC,0x34,0xA5,0xE5,0xF1,0x71,0xD8,0x31,0x15,0x04,0xC7,0x23,0xC3,0x18,0x96,0x05,0x9A,0x07,0x12,0x80,0xE2,0xEB,0x27,0xB2,0x75,0x09,0x83,0x2C,0x1A,0x1B,0x6E,0x5A,0xA0,0x52,0x3B,0xD6,0xB3,0x29,0xE3,0x2F,0x84,0x53,0xD1,0x00,0xED,0x20,0xFC,0xB1,0x5B,0x6A,0xCB,0xBE,0x39,0x4A,0x4C,0x58,0xCF,0xD0,0xEF,0xAA,0xFB,0x43,0x4D,0x33,0x85,0x45,0xF9,0x02,0x7F,0x50,0x3C,0x9F,0xA8,0x51,0xA3,0x40,0x8F,0x92,0x9D,0x38,0xF5,0xBC,0xB6,0xDA,0x21,0x10,0xFF,0xF3,0xD2,0xCD,0x0C,0x13,0xEC,0x5F,0x97,0x44,0x17,0xC4,0xA7,0x7E,0x3D,0x64,0x5D,0x19,0x73,0x60,0x81,0x4F,0xDC,0x22,0x2A,0x90,0x88,0x46,0xEE,0xB8,0x14,0xDE,0x5E,0x0B,0xDB,0xE0,0x32,0x3A,0x0A,0x49,0x06,0x24,0x5C,0xC2,0xD3,0xAC,0x62,0x91,0x95,0xE4,0x79,0xE7,0xC8,0x37,0x6D,0x8D,0xD5,0x4E,0xA9,0x6C,0x56,0xF4,0xEA,0x65,0x7A,0xAE,0x08,0xBA,0x78,0x25,0x2E,0x1C,0xA6,0xB4,0xC6,0xE8,0xDD,0x74,0x1F,0x4B,0xBD,0x8B,0x8A,0x70,0x3E,0xB5,0x66,0x48,0x03,0xF6,0x0E,0x61,0x35,0x57,0xB9,0x86,0xC1,0x1D,0x9E,0xE1,0xF8,0x98,0x11,0x69,0xD9,0x8E,0x94,0x9B,0x1E,0x87,0xE9,0xCE,0x55,0x28,0xDF,0x8C,0xA1,0x89,0x0D,0xBF,0xE6,0x42,0x68,0x41,0x99,0x2D,0x0F,0xB0,0x54,0xBB,0x16]INV_SBOX[0]*256foriinrange(256):INV_SBOX[SBOX[i]]i# 逆向移位definv_shift_rows(s):return[s[0],s[13],s[10],s[7],s[4],s[1],s[14],s[11],s[8],s[5],s[2],s[15],s[12],s[9],s[6],s[3]]defgf_mult(a,b):p0for_inrange(8):ifb1:p^a hi_bit_seta0x80a(a1)0xFFifhi_bit_set:a^0x1bb1returnpdefinv_mix_columns(s):out[0]*16foriinrange(0,16,4):cs[i:i4]out[i]gf_mult(0x0e,c[0])^gf_mult(0x0b,c[1])^gf_mult(0x0d,c[2])^gf_mult(0x09,c[3])out[i1]gf_mult(0x09,c[0])^gf_mult(0x0e,c[1])^gf_mult(0x0b,c[2])^gf_mult(0x0d,c[3])out[i2]gf_mult(0x0d,c[0])^gf_mult(0x09,c[1])^gf_mult(0x0e,c[2])^gf_mult(0x0b,c[3])out[i3]gf_mult(0x0b,c[0])^gf_mult(0x0d,c[1])^gf_mult(0x09,c[2])^gf_mult(0x0e,c[3])returnout# AES解密defdecrypt_block(block,round_keys):statelist(block)# 第一步异或最后一轮密钥 (Round 14)state[a^bfora,binzip(state,round_keys[14])]# 中间 13 轮逆向推导forround_idxinrange(13,0,-1):stateinv_shift_rows(state)state[INV_SBOX[b]forbinstate]state[a^bfora,binzip(state,round_keys[round_idx])]stateinv_mix_columns(state)# 最后一轮 (Round 0)stateinv_shift_rows(state)state[INV_SBOX[b]forbinstate]state[a^bfora,binzip(state,round_keys[0])]returnstate# CBC 解密链ptbytearray()prevlist(iv)foriinrange(0,len(ct),16):blockct[i:i16]dec_blockdecrypt_block(block,round_keys)pt_block[a^bfora,binzip(dec_block,prev)]pt.extend(pt_block)prevblock# 去除PKCS#7填充pad_lenpt[-1]flagpt[:-pad_len].decode(utf-8,errorsignore)print(flag)FLAG得到flagdart{c3d4f5cc-8aab-46ce-a188-2fc453f3b288}
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2422202.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!