REVERSE-PRACTICE-BUUCTF-21

REVERSE-PRACTICE-BUUCTF-21

    • [SCTF2019]babyre
    • [MRCTF2020]EasyCpp
    • [GUET-CTF2019]encrypt
    • [QCTF2018]Xman-babymips

[SCTF2019]babyre

elf文件,无壳,用ida分析
在start函数中看到main函数的字样,但是左侧函数窗没有找到main函数
原因是main函数中加了花指令,导致ida不能正确地分析main函数
main函数中有三处类似这样的花指令,把jb,jnb,loope三条指令都nop掉,创建函数,F5反编译
babyre-fakecode
main函数中要求输入三个password,三个pwd都正确才能得到flag
先看第一个password的部分,是个走迷宫的逻辑
v28~v44是迷宫的map,长度为125,起点为’s’
往下走,switch case语句是由输入pwd1的字符决定方向,w-上,s-下,d-右,a-左,x-下一块,y-上一块,由此可以知道,长度为125的map,每25分为一个块,每个块又是5x5排列,路线只能走’.’,终点为’#’,要求最短的路线

  v28 = '********';                             // 注意小端序v29 = '*.******';v30 = '.s**.***';v31 = '****..*.';v32 = '.****.**';v33 = '********';v34 = '***..***';v35 = '*#..**..';v36 = '*..***..';v37 = '*****.**';v38 = '********';v39 = '.*******';v40 = '****..**';v41 = '.**..***';v42 = '*.*..*..';v43 = '.**.';v44 = '*';v10 = 0LL;v11 = 0LL;v12 = 0;v7 = (char *)&v30 + 6;                        // 起点为's'v8 = '019_ftcs';                              // v8='sctf_9102'v9 = '2';puts((const char *)(unsigned int)"plz tell me the shortest password1:");scanf("%s", &pwd1);v6 = 1;while ( v6 ){v4 = *((_BYTE *)&pwd1 + v5);switch ( v4 ){case 'w':v7 -= 5;break;case 's':v7 += 5;break;case 'd':++v7;break;case 'a':--v7;break;case 'x':v7 += 25;break;case 'y':v7 -= 25;break;default:v6 = 0;break;}++v5;if ( *v7 != '.' && *v7 != '#' )             // 只能走'.'v6 = 0;if ( *v7 == '#' )                           // 最后到'#'{puts("good!you find the right way!\nBut there is another challenge!");break;}}

将长度为125的map按照每25一块,每块5x5排列的方式,按w-上,s-下,d-右,a-左,x-下一块,y-上一块的规定,得到最短的路线为sxss,验证正确
babyre-route
往下走,看第二个password的部分
pwd2和v17作为参数传入loc_C22逻辑段的函数,过程中v17被赋值,函数返回后v17和v8比较,已知v8是字符串"sctf_9102"

  if ( v6 ){puts((const char *)(unsigned int)"plz tell me the password2:");scanf("%s", &pwd2);((void (__fastcall *)(__int64 *, __int64 *))loc_C22)(&pwd2, &v17);if ( (unsigned int)sub_F67((const char *)&v17, (const char *)&v8) == 1 )// v17和v8比较,v8='sctf_9102'{puts("Congratulation!");

loc_C22逻辑段的代码也被插入了花指令,jb和jnb直接nop掉,“in"指令的第一个字节改成0x90
下面未被识别成代码的数据按d转成一个一个字节的形式,把前两个值为0的字节改成0x90
创建函数,F5反编译
babyre-fakecode
进入sub_C22函数,来到给v17赋值的部分
0x3f的二进制为0b00111111,v7又被v7<<6赋值,v9等于4时才会进入if语句给v17赋值,由6x4=8x3,猜测是base64的反编码过程,反编码的结果为v8的字符串"sctf_9102”,于是pwd2为v8的base64编码,即为"c2N0Zl85MTAy",验证正确
babyre-sub_C22
往下走,看第三个password的部分
pwd3进入sub_FFA函数进行验证,返回1验证成功

      puts((const char *)(unsigned int)"Now,this is the last!");puts("plz tell me the password3:");scanf("%s", &pwd3);if ( (unsigned int)sub_FFA(&pwd3) == 1 ){puts("Congratulation!Here is your flag!:");printf("sctf{%s-%s(%s)}", &pwd1, &pwd2, &pwd3);}

进入sub_FFA函数,将输入的pwd3按大端序规则,16个byte转成4个int,do循环体中的sub_143B进行变换和赋值,最后四次循环赋值给v44~v47,v44到v47的4个int按大端序规则,转成16个byte,与v8比较验证

signed __int64 __fastcall sub_FFA(char *pwd3)
{int v1; // ST24_4int v2; // ST28_4int v3; // ST2C_4signed int v5; // [rsp+18h] [rbp-158h]signed int i; // [rsp+18h] [rbp-158h]int v7; // [rsp+1Ch] [rbp-154h]int v8; // [rsp+30h] [rbp-140h]int v9; // [rsp+34h] [rbp-13Ch]int v10; // [rsp+38h] [rbp-138h]int v11; // [rsp+3Ch] [rbp-134h]int v12; // [rsp+40h] [rbp-130h]int v13; // [rsp+44h] [rbp-12Ch]int v14; // [rsp+48h] [rbp-128h]int v15; // [rsp+4Ch] [rbp-124h]int v16; // [rsp+50h] [rbp-120h]int v17; // [rsp+54h] [rbp-11Ch]int v18; // [rsp+58h] [rbp-118h]int v19; // [rsp+5Ch] [rbp-114h]int v20; // [rsp+60h] [rbp-110h]int v21; // [rsp+64h] [rbp-10Ch]int v22; // [rsp+68h] [rbp-108h]int v23; // [rsp+6Ch] [rbp-104h]unsigned int v24; // [rsp+70h] [rbp-100h]int v25; // [rsp+74h] [rbp-FCh]int v26; // [rsp+78h] [rbp-F8h]int v27; // [rsp+7Ch] [rbp-F4h]unsigned int v28; // [rsp+80h] [rbp-F0h]int v29; // [rsp+84h] [rbp-ECh]int v30; // [rsp+88h] [rbp-E8h]int v31; // [rsp+8Ch] [rbp-E4h]unsigned int v32; // [rsp+90h] [rbp-E0h]int v33; // [rsp+94h] [rbp-DCh]int v34; // [rsp+98h] [rbp-D8h]int v35; // [rsp+9Ch] [rbp-D4h]unsigned int v36; // [rsp+A0h] [rbp-D0h]int v37; // [rsp+A4h] [rbp-CCh]int v38; // [rsp+A8h] [rbp-C8h]int v39; // [rsp+ACh] [rbp-C4h]int v40; // [rsp+B0h] [rbp-C0h]int v41; // [rsp+B4h] [rbp-BCh]int v42; // [rsp+B8h] [rbp-B8h]int v43; // [rsp+BCh] [rbp-B4h]unsigned int v44; // [rsp+118h] [rbp-58h]unsigned int v45; // [rsp+11Ch] [rbp-54h]unsigned int v46; // [rsp+120h] [rbp-50h]unsigned int v47; // [rsp+124h] [rbp-4Ch]unsigned __int64 v48; // [rsp+168h] [rbp-8h]v48 = __readfsqword(0x28u);v8 = 0xBE;v9 = 4;v10 = 6;v11 = 0x80;v12 = 0xC5;v13 = 0xAF;v14 = 0x76;v15 = 0x47;v16 = 0x9F;v17 = 0xCC;v18 = 0x40;v19 = 0x1F;v20 = 0xD8;v21 = 0xBF;v22 = 0x92;v23 = 0xEF;v1 = (pwd3[6] << 8) | (pwd3[5] << 16) | (pwd3[4] << 24) | pwd3[7];// 大端序v2 = (pwd3[10] << 8) | (pwd3[9] << 16) | (pwd3[8] << 24) | pwd3[11];v3 = (pwd3[14] << 8) | (pwd3[13] << 16) | (pwd3[12] << 24) | pwd3[15];v7 = 0;v5 = 4;v40 = sub_78A((pwd3[2] << 8) | (pwd3[1] << 16) | (*pwd3 << 24) | (unsigned int)pwd3[3]);// 大端序v41 = sub_78A(v1);v42 = sub_78A(v2);v43 = sub_78A(v3);                            // v40~v43被pwd3赋值,按大端序规则,16个byte转成4个intdo{*(&v40 + v5) = sub_143B(*(&v40 + v7), *(&v40 + v7 + 1), *(&v40 + v7 + 2), *(&v40 + v7 + 3));// 变换++v7;++v5;}while ( v5 <= 29 );v24 = v44 >> 24;                              // do循环体填充v43~v44之间的地址,v44~v47是最后四次循环被赋值v25 = BYTE2(v44);v26 = BYTE1(v44);v27 = (unsigned __int8)v44;v28 = v45 >> 24;v29 = BYTE2(v45);v30 = BYTE1(v45);v31 = (unsigned __int8)v45;v32 = v46 >> 24;v33 = BYTE2(v46);v34 = BYTE1(v46);v35 = (unsigned __int8)v46;v36 = v47 >> 24;v37 = BYTE2(v47);v38 = BYTE1(v47);v39 = (unsigned __int8)v47;for ( i = 0; i <= 15; ++i ){if ( *(&v24 + i) != *(&v8 + i) )            // v44~v47的4个int分成16个byte,与v8比较return 0xFFFFFFFFLL;}return 1LL;
}

sub_143B函数,异或运算

__int64 __fastcall sub_143B(int a1, int a2, int a3, unsigned int a4)
{return a1 ^ (unsigned int)sub_1464(a2 ^ a3 ^ a4);
}

sub_1464函数,主要也是异或运算

__int64 __fastcall sub_1464(unsigned int a1)
{int v1; // ST18_4int v3[290]; // [rsp+20h] [rbp-490h]unsigned __int64 v4; // [rsp+4A8h] [rbp-8h]v4 = __readfsqword(0x28u);qmemcpy(v3, &off_1940, 1152uLL);v1 = (v3[BYTE2(a1)] << 16) | v3[(unsigned __int8)a1] | (v3[BYTE1(a1)] << 8) | (v3[a1 >> 24] << 24);return __ROL4__(v1, 12) ^ (unsigned int)(__ROL4__(v1, 8) ^ __ROR4__(v1, 2)) ^ __ROR4__(v1, 6);
}

于是do循环体中的变换赋值主要是异或运算,直接可逆,sub_1464函数的代码直接用,写脚本即可解出pwd3

#include <stdio.h>
#include "ida_defs.h"
unsigned int off_1940[288] = {0xD6, 0x90, 0xE9, 0xFE, 0xCC, 0xE1, 0x3D, 0xB7,0x16, 0xB6, 0x14, 0xC2, 0x28, 0xFB, 0x2C, 0x05,0x2B, 0x67, 0x9A, 0x76, 0x2A, 0xBE, 0x04, 0xC3,0xAA, 0x44, 0x13, 0x26, 0x49, 0x86, 0x06, 0x99,0x9C, 0x42, 0x50, 0xF4, 0x91, 0xEF, 0x98, 0x7A,0x33, 0x54, 0x0B, 0x43, 0xED, 0xCF, 0xAC, 0x62,0xE4, 0xB3, 0x1C, 0xA9, 0xC9, 0x08, 0xE8, 0x95,0x80, 0xDF, 0x94, 0xFA, 0x75, 0x8F, 0x3F, 0xA6,0x47, 0x07, 0xA7, 0xFC, 0xF3, 0x73, 0x17, 0xBA,0x83, 0x59, 0x3C, 0x19, 0xE6, 0x85, 0x4F, 0xA8,0x68, 0x6B, 0x81, 0xB2, 0x71, 0x64, 0xDA, 0x8B,0xF8, 0xEB, 0x0F, 0x4B, 0x70, 0x56, 0x9D, 0x35,0x1E, 0x24, 0x0E, 0x5E, 0x63, 0x58, 0xD1, 0xA2,0x25, 0x22, 0x7C, 0x3B, 0x01, 0x21, 0x78, 0x87,0xD4, 0x00, 0x46, 0x57, 0x9F, 0xD3, 0x27, 0x52,0x4C, 0x36, 0x02, 0xE7, 0xA0, 0xC4, 0xC8, 0x9E,0xEA, 0xBF, 0x8A, 0xD2, 0x40, 0xC7, 0x38, 0xB5,0xA3, 0xF7, 0xF2, 0xCE, 0xF9, 0x61, 0x15, 0xA1,0xE0, 0xAE, 0x5D, 0xA4, 0x9B, 0x34, 0x1A, 0x55,0xAD, 0x93, 0x32, 0x30, 0xF5, 0x8C, 0xB1, 0xE3,0x1D, 0xF6, 0xE2, 0x2E, 0x82, 0x66, 0xCA, 0x60,0xC0, 0x29, 0x23, 0xAB, 0x0D, 0x53, 0x4E, 0x6F,0xD5, 0xDB, 0x37, 0x45, 0xDE, 0xFD, 0x8E, 0x2F,0x03, 0xFF, 0x6A, 0x72, 0x6D, 0x6C, 0x5B, 0x51,0x8D, 0x1B, 0xAF, 0x92, 0xBB, 0xDD, 0xBC, 0x7F,0x11, 0xD9, 0x5C, 0x41, 0x1F, 0x10, 0x5A, 0xD8,0x0A, 0xC1, 0x31, 0x88, 0xA5, 0xCD, 0x7B, 0xBD,0x2D, 0x74, 0xD0, 0x12, 0xB8, 0xE5, 0xB4, 0xB0,0x89, 0x69, 0x97, 0x4A, 0x0C, 0x96, 0x77, 0x7E,0x65, 0xB9, 0xF1, 0x09, 0xC5, 0x6E, 0xC6, 0x84,0x18, 0xF0, 0x7D, 0xEC, 0x3A, 0xDC, 0x4D, 0x20,0x79, 0xEE, 0x5F, 0x3E, 0xD7, 0xCB, 0x39, 0x48,0xC6, 0xBA, 0xB1, 0xA3, 0x50, 0x33, 0xAA, 0x56,0x97, 0x91, 0x7D, 0x67, 0xDC, 0x22, 0x70, 0xB2,0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};unsigned int sub_1464(unsigned int a1)
{int v1;v1 = (off_1940[BYTE2(a1)] << 16) | off_1940[(unsigned __int8)a1] | (off_1940[BYTE1(a1)] << 8) | (off_1940[a1 >> 24] << 24);return __ROL4__(v1, 12) ^ (unsigned int)(__ROL4__(v1, 8) ^ __ROR4__(v1, 2)) ^ __ROR4__(v1, 6);
}int main()
{unsigned int v40[30] = { 0 };v40[26] = 0xBE040680;v40[27] = 0xC5AF7647;v40[28] = 0x9FCC401F;v40[29] = 0xD8BF92EF;int i;for (i = 25; i >= 0; i--)v40[i] = sub_1464(v40[i + 1] ^ v40[i + 2] ^ v40[i + 3]) ^ v40[i + 4];for (i = 0; i < 4; i++)printf("%c%c%c%c", ((char*)&v40[i])[0], ((char*)&v40[i])[1], ((char*)&v40[i])[2], ((char*)&v40[i])[3]);return 0;
//fl4g_is_s0_ug1y!
}

将三个password输入,得到flag
但是提交失败,看里别的师傅的wp,第一个password走迷宫出错了
正确的pwd1为ddwwxxssxaxwwaasasyywwdd
于是flag为sctf{ddwwxxssxaxwwaasasyywwdd-c2N0Zl85MTAy(fl4g_is_s0_ug1y!)}
babyre-flag

[MRCTF2020]EasyCpp

elf文件,无壳,ida分析
main函数,读取输入,输入赋到v21,利用迭代器将v21从头到尾全部异或1
easycpp-part1
异或1后的输入进入depart函数,将输入分解成其因子,各因子间用空格分隔,结果放到v15,v15进入func进行替换,数字变字符,空格变等号,替换后的结果进入check与已知比较
easycpp-part2
depart函数
easycpp-depart
写逆运算脚本即可得到正确的输入

#coding:utf-8
res=['=zqE=z=z=z','=lzzE','=ll=T=s=s=E','=zATT','=s=s=s=E=E=E','=EOll=E','=lE=T=E=E=E','=EsE=s=z','=AT=lE=ll']
for s in res:ss=s.replace('O','0').replace('l','1').replace('z','2').replace('E','3').replace('A','4').replace('s','5').replace('G','6').replace('T','7').replace('B','8').replace('q','9').replace('=',' ')data=ss.split(' ')[1:] #第0个均为空格 故从第1个开始sum=1for i in data:         #乘回去sum*=int(i,10)sum^=1                  #异或1print(sum),
#2345 1222 5774 2476 3374 9032 2456 3531 6720

将数字串取32位大写md5散列即可提交成功
easycpp-flag

[GUET-CTF2019]encrypt

elf文件,无壳,ida分析
main函数,逻辑清晰,读取输入,对输入进行RC4加密,再进行很像base64的变换,只是没有从表中取值,变换后的输入与已知的数据比较,验证输入

__int64 __fastcall main(__int64 a1, char **a2, char **a3)
{int v3; // eaxint v4; // eaxchar v6; // [rsp+4h] [rbp-93Ch]int i; // [rsp+8h] [rbp-938h]int v8; // [rsp+Ch] [rbp-934h]char v9; // [rsp+10h] [rbp-930h]char v10; // [rsp+420h] [rbp-520h]char v11; // [rsp+421h] [rbp-51Fh]char v12; // [rsp+422h] [rbp-51Eh]char v13; // [rsp+423h] [rbp-51Dh]char v14; // [rsp+424h] [rbp-51Ch]char v15; // [rsp+425h] [rbp-51Bh]char v16; // [rsp+426h] [rbp-51Ah]char v17; // [rsp+427h] [rbp-519h]char input; // [rsp+430h] [rbp-510h]char v19[1032]; // [rsp+530h] [rbp-410h]unsigned __int64 v20; // [rsp+938h] [rbp-8h]v20 = __readfsqword(0x28u);v10 = 16;v11 = 32;v12 = 48;v13 = 48;v14 = 32;v15 = 32;v16 = 16;v17 = 64;memset(&input, 0, 0x100uLL);v8 = strlen(&input);memset(v19, 0, 0x400uLL);printf("please input your flag:", a2, v19);scanf("%s", &input);                          // 获取输入memset(&v9, 0, 1032uLL);RC4_S(&v9, (__int64)&v10, 8);                 // RC4加密算法,生成S盒,打乱S盒,密钥为v10~17的8个字节v3 = strlen(&input);RC4_encrypt(&v9, (__int64)&input, v3);        // RC4加密算法,对输入进行异或加密v4 = strlen(&input);base64_like((__int64)&input, v4, v19, &v6);   // 对加密后的输入进行变换,变换结构很像base64,变换的结果放到v19for ( i = 0; i <= 50; ++i ){if ( v19[i] != res[i] )                     // v19与res比较,验证输入{puts("Wrong");return 0LL;}}puts("Good");return 0LL;
}

由最后要比较的数据,逆很像base64的变换,得到输入经RC4加密后的密文

res="Z`TzzTrD|fQP[_VVL|yneURyUmFklVJgLasJroZpHRxIUlH\\vZE="
data=[]
for i in range(len(res)-1):data.append(ord(res[i])-61)
data.append(ord('='))
cipher=[]
for i in range(0,len(data),4):tmp=bin(data[i]).replace('0b','').zfill(6)+bin(data[i+1]).replace('0b','').zfill(6)+bin(data[i+2]).replace('0b','').zfill(6)+bin(data[i+3]).replace('0b','').zfill(6)a=int('0b'+tmp[0:8],2)b=int('0b'+tmp[8:16],2)c=int('0b'+tmp[16:24],2)cipher.append(a)cipher.append(b)cipher.append(c)
print(cipher)
#[118, 53, 253, 245, 125, 71, 254, 149, 19, 122, 38, 89, 63, 255, 49, 161, 133, 124, 99, 2, 110, 189, 147, 106, 62, 77, 141, 215, 39, 115, 45, 94, 204, 98, 242, 223, 229, 210, 61]

由已知的密钥(v10~v17的8个字节)和密文cipher,解密RC4,即可得到flag

#include<stdio.h>
void rc4_init(unsigned char* s, unsigned char* key, unsigned long Len_k) //初始化函数
{int i = 0, j = 0;char k[256] = { 0 };unsigned char tmp = 0;for (i = 0; i < 256; i++) {s[i] = i;k[i] = key[i % Len_k];}for (i = 0; i < 256; i++) {j = (j + s[i] + k[i]) % 256;tmp = s[i];s[i] = s[j]; s[j] = tmp;}
}/*
RC4加解密函数
unsigned char* Data     加解密的数据
unsigned long Len_D     加解密数据的长度
unsigned char* key      密钥
unsigned long Len_k     密钥长度
*/
void rc4_crypt(unsigned char* Data, unsigned long Len_D, unsigned char* key, unsigned long Len_k) //加解密
{unsigned char s[256];rc4_init(s, key, Len_k);int i = 0, j = 0, t = 0;unsigned long k = 0;unsigned char tmp;for (k = 0; k < Len_D; k++) {i = (i + 1) % 256;j = (j + s[i]) % 256;tmp = s[i];s[i] = s[j]; s[j] = tmp;t = (s[i] + s[j]) % 256;Data[k] = Data[k] ^ s[t];}
}
void main()
{//密钥unsigned char key[] = {16,32,48,48,32,32,16,64};//密钥长度 unsigned long key_len = sizeof(key);//密文unsigned char data[] = { 118, 53, 253, 245, 125, 71, 254, 149, 19, 122, 38, 89, 63, 255, 49, 161, 133, 124, 99, 2, 110, 189, 147, 106, 62, 77, 141, 215, 39, 115, 45, 94, 204, 98, 242, 223, 229, 210, 61 };//解密rc4_crypt(data, sizeof(data), key, key_len);for (int i = 0; i < sizeof(data); i++){printf("%c", data[i]);}
}
//flag{e10adc3949ba59abbe56e057f20f883e}

[QCTF2018]Xman-babymips

mips文件,无壳,用ida7.5打开(其他版本的ida可能不能反编译mips)
main函数,读取输入,长度为32,先进行input[i]^=32-i的变换,变换后的input的前5个字符与"Q|j{g"比较,相同时进入sub_4007F0函数,对后27个字符再进行变换
xmanmips-main
sub_4007F0函数,不考虑前5个字符,下标从5开始,分奇偶数对输入进行移位变换,变换后与已知数据比较
xmanmips-sub_4007F0
写逆脚本即可得到flag

#coding:utf-8
s="Q|j{g"
off_410D04=[0,0,0,0,0,0x52, 0xFD, 0x16, 0xA4, 0x89, 0xBD, 0x92, 0x80, 0x13, 0x41,0x54, 0xA0, 0x8D, 0x45, 0x18, 0x81, 0xDE, 0xFC, 0x95, 0xF0,0x16, 0x79, 0x1A, 0x15, 0x5B, 0x75, 0x1F] #前面补5个0,保持下标一致
flag=[0]*32
for i in range(len(s)):flag[i]=ord(s[i])
for i in range(5,len(off_410D04)):if i&1:flag[i]=(off_410D04[i]<<2)&0xfc|(off_410D04[i]>>6)&0x03else:flag[i]=(off_410D04[i]>>2)&0x3f|(off_410D04[i]<<6)&0xc0
for i in range(len(flag)):flag[i]^=32-i
print(''.join(chr(i) for i in flag))
#qctf{ReA11y_4_B@89_mlp5_4_XmAn_}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/438151.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

原型设计工具——“墨刀”的介绍与基本教程

一、产品介绍 &#xff08;1&#xff09;产品简介&#xff1a; 墨刀是一款在线原型设计与协同工具&#xff0c;借助墨刀&#xff0c;产品经理、设计师、开发、销售、运营及创业者等用户群体&#xff0c;能够搭建为产品原型&#xff0c;演示项目效果。 &#xff08;2&#xf…

MockPlus原型设计介绍

在第八周的课堂上&#xff0c;王文娟老师在校园系统上发布了对于自行选择的原型设计软件进行资料查找以及自学的任务。因为之前的课程学习需要&#xff0c;我们已经大概掌握了原型设计软件Axure的使用&#xff0c;因此在这里&#xff0c;我选择了另一原型设计进行介绍&#xff…

REVERSE-PRACTICE-BUUCTF-22

REVERSE-PRACTICE-BUUCTF-22[SCTF2019]Who is he[FlareOn2]very_success[NPUCTF2020]Baby Obfuscation[HDCTF2019]MFC[SCTF2019]Who is he unity游戏&#xff0c;运行后输入&#xff0c;点击按钮检验输入 dnSpy打开Who is he\Who is he_Data\Managed\Assembly-CSharp.dll 在Te…

浅谈常见的NoSQL技术方案和选型

前言 在互联网和大数据的背景下&#xff0c;越来越多的网站、应用系统需要支撑 海量数据存储、高并发请求、高可用、高可扩展性 等特性要求。传统的 关系型数据库 已经难以应对类似的需求&#xff0c;各种各样的 NoSQL&#xff08;Not Only SQL&#xff09;数据库因此而产生。…

REVERSE-PRACTICE-BUUCTF-23

REVERSE-PRACTICE-BUUCTF-23[2019红帽杯]Snake[BSidesSF2019]blink[De1CTF2019]Re_Sign[ACTF新生赛2020]Splendid_MineCraft[2019红帽杯]Snake unity游戏&#xff0c;dnSpy打开Snake\Snake_Data\Managed\Assembly-CSharp.dll 发现要载入Interface这个dll ida打开Snake\Snake_…

REVERSE-PRACTICE-BUUCTF-24

REVERSE-PRACTICE-BUUCTF-24[watevrCTF 2019]Timeout[SUCTF2019]hardcpp[CISCN2018]2ex[UTCTF2020]babymips[watevrCTF 2019]Timeout elf文件&#xff0c;无壳&#xff0c;ida分析 main函数中signal&#xff0c;alarm&#xff0c;delay三个函数配合使用是为了反调试 交叉引用…

REVERSE-PRACTICE-BUUCTF-25

REVERSE-PRACTICE-BUUCTF-25特殊的 BASE64[FlareOn1]Javascrap[WMCTF2020]easy_re[NPUCTF2020]BasicASM特殊的 BASE64 exe程序&#xff0c;运行后输入&#xff0c;无壳&#xff0c;ida分析 main函数&#xff0c;读取输入&#xff0c;进行变表base64编码&#xff0c;与rightFla…

REVERSE-PRACTICE-BUUCTF-26

REVERSE-PRACTICE-BUUCTF-26[FlareOn6]FlareBear[SUCTF2018]babyre[GKCTF2020]WannaReverse[FlareOn4]greek_to_me[FlareOn6]FlareBear apk文件&#xff0c;模拟器上运行&#xff0c;创建一个小熊&#xff0c;有三种方式交互&#xff0c;分别为“吃饭”&#xff0c;“篮球”以…

C#的变迁史02 - C# 2.0篇

在此重申一下&#xff0c;本文仅代表个人观点&#xff0c;如有不妥之处&#xff0c;还请自己辨别。 第一代的值类型装箱与拆箱的效率极其低下&#xff0c;特别是在集合中的表现&#xff0c;所以第二代C#重点解决了装箱的问题&#xff0c;加入了泛型。1. 泛型 - 珍惜生命&#x…

REVERSE-PRACTICE-BUUCTF-27

REVERSE-PRACTICE-BUUCTF-27[XMAN2018排位赛]Dragon Quest[羊城杯 2020]easyre[watevrCTF 2019]Repyc[2019红帽杯]calc[XMAN2018排位赛]Dragon Quest elf文件&#xff0c;无壳&#xff0c;ida分析 main函数&#xff0c;读取输入&#xff0c;start_quest函数验证输入&#xff0…

C#的变迁史03 - C# 3.0篇

C# 3.0 (.NET 3.5, VS2008) 第三代C#在语法元素基本完备的基础上提供了全新的开发工具和集合数据查询方式&#xff0c;极大的方便了开发。 1. WPF&#xff0c;WCF&#xff0c;WF 这3个工程类型奠定了新一代.NET开发的客户端模型&#xff0c;通信模型&#xff0c;工作流模型。 …

REVERSE-PRACTICE-BUUCTF-28

REVERSE-PRACTICE-BUUCTF-28[FlareOn6]Memecat Battlestation[b01lers2020]chugga_chugga[INSHack2018]Tricky-Part1[watevrCTF 2019]esreveR[FlareOn6]Memecat Battlestation .Net程序&#xff0c;运行后输入weapon code&#xff0c;用dnSpy打开 在Stage1Form直接找到第一个w…

C#的变迁史04 - C# 4.0 之多线程篇

在.NET 4.0中&#xff0c;并行计算与多线程得到了一定程度的加强&#xff0c;这主要体现在并行对象Parallel&#xff0c;多线程Task&#xff0c;与PLinq。这里对这些相关的特性一起总结一下。 使用Thread方式的线程无疑是比较麻烦的&#xff0c;于是在这个版本中有了改善的版本…

REVERSE-PRACTICE-BUUCTF-29

REVERSE-PRACTICE-BUUCTF-29[FlareOn1]Shellolololol[CFI-CTF 2018]powerPacked[INSHack2018]Tricky-Part2[CFI-CTF 2018]Automated Reversing[FlareOn1]Shellolololol exe程序&#xff0c;直接不能运行&#xff0c;无壳&#xff0c;ida分析 简单F8单步调试发现&#xff0c;在…

C#的变迁史05 - C# 4.0篇

C# 4.0 (.NET 4.0, VS2010) 第四代C#借鉴了动态语言的特性&#xff0c;搞出了动态语言运行时&#xff0c;真的是全面向“高大上”靠齐啊。 1. DLR动态语言运行时 C#作为静态语言&#xff0c;它需要编译以后运行&#xff0c;在编译的过程中&#xff0c;编译器要检查语法的正确性…

REVERSE-PRACTICE-BUUCTF-30

REVERSE-PRACTICE-BUUCTF-30[RCTF2019]DontEatMe[b01lers2020]little_engine[NPUCTF2020]你好sao啊[MRCTF2020]Shit[RCTF2019]DontEatMe exe程序&#xff0c;运行后输入&#xff0c;无壳&#xff0c;用ida分析 交叉引用字符串来到sub_401260函数&#xff0c;读取输入&#xff…

C#的变迁史06 - C# 4.0 之并行处理篇

前面看完了Task对象&#xff0c;这里再看一下另一个息息相关的对象Parallel。 Parallel对象 Parallel对象封装了能够利用多核并行执行的多线程操作&#xff0c;其内部使用Task来分装多线程的任务并试图将它们分配到不同的内核中并行执行。请注意“试图”这个词&#xff0c;Par…

REVERSE-PRACTICE-BUUCTF-31

REVERSE-PRACTICE-BUUCTF-31[羊城杯 2020]login[羊城杯 2020]Bytecode[羊城杯 2020]babyre[ACTF新生赛2020]fungame[羊城杯 2020]login exe程序&#xff0c;运行后输入&#xff0c;无壳&#xff0c;ida分析 没找到主要逻辑&#xff0c;在字符串窗口看到一些“py”的字样&#…

C#的变迁史07 - C# 4.0 之线程安全集合篇

作为多线程和并行计算不得不考虑的问题就是临界资源的访问问题&#xff0c;解决临界资源的访问通常是加锁或者是使用信号量&#xff0c;这个大家应该很熟悉了。 而集合作为一种重要的临界资源&#xff0c;通用性更广&#xff0c;为了让大家更安全的使用它们&#xff0c;微软为我…

PWN-PRACTICE-BUUCTF-1

PWN-PRACTICE-BUUCTF-1test_your_ncripwarmup_csaw_2016ciscn_2019_n_1test_your_nc 附件的main函数直接system("/bin/sh")&#xff0c;nc直接连即可cat flag rip main函数中&#xff0c;gets函数读取一行会造成栈溢出 构造payload覆盖rip&#xff0c;使得return…