19,Hack-you-2014_Newbie_calculations
在main里边有一大堆运算(极慢不可实现的)调用3个函数,这3个函数通过垃圾运算实现了 加、减、乘(调用加)三个功能。手工把main里函数改个名方便看:
for ( i = 0; i < 32; ++i )
v120[i] = 1;
v121 = 0;
puts("Your flag is:");
v3 = mul(v120, 1000000000);
v4 = sub(v3, 999999950);
mul(v4, 2);
v5 = add(&v120[1], 5000000);
v6 = sub(v5, 6666666);
v7 = add(v6, 1666666);
v8 = add(v7, 45);
v9 = mul(v8, 2);
add(v9, 5);
v10 = mul(&v120[2], 1000000000);
v11 = sub(v10, 999999950);
v12 = mul(v11, 2);
add(v12, 2);
v13 = add(&v120[3], 55);
v14 = sub(v13, 3);
v15 = add(v14, 4);
sub(v15, 1);
v16 = mul(&v120[4], 100000000);
v17 = sub(v16, 99999950);
v18 = mul(v17, 2);
add(v18, 2);
v19 = sub(&v120[5], 1);
v20 = mul(v19, 1000000000);
v21 = add(v20, 55);
sub(v21, 3);
v22 = mul(&v120[6], 1000000);
v23 = sub(v22, 999975);
mul(v23, 4);
v24 = add(&v120[7], 55);
v25 = sub(v24, 33);
v26 = add(v25, 44);
sub(v26, 11);
v27 = mul(&v120[8], 10);
v28 = sub(v27, 5);
v29 = mul(v28, 8);
add(v29, 9);
v30 = add(&v120[9], 0);
v31 = sub(v30, 0);
v32 = add(v31, 11);
v33 = sub(v32, 11);
add(v33, 53);
v34 = add(&v120[10], 49);
v35 = sub(v34, 2);
v36 = add(v35, 4);
sub(v36, 2);
v37 = mul(&v120[11], 1000000);
v38 = sub(v37, 999999);
v39 = mul(v38, 4);
add(v39, 50);
v40 = add(&v120[12], 1);
v41 = add(v40, 1);
v42 = add(v41, 1);
v43 = add(v42, 1);
v44 = add(v43, 1);
v45 = add(v44, 1);
v46 = add(v45, 10);
add(v46, 32);
v47 = mul(&v120[13], 10);
v48 = sub(v47, 5);
v49 = mul(v48, 8);
v50 = add(v49, 9);
add(v50, 48);
v51 = sub(&v120[14], 1);
v52 = mul(v51, -294967296);
v53 = add(v52, 55);
sub(v53, 3);
v54 = add(&v120[15], 1);
v55 = add(v54, 2);
v56 = add(v55, 3);
v57 = add(v56, 4);
v58 = add(v57, 5);
v59 = add(v58, 6);
v60 = add(v59, 7);
add(v60, 20);
v61 = mul(&v120[16], 10);
v62 = sub(v61, 5);
v63 = mul(v62, 8);
v64 = add(v63, 9);
add(v64, 48);
v65 = add(&v120[17], 7);
v66 = add(v65, 6);
v67 = add(v66, 5);
v68 = add(v67, 4);
v69 = add(v68, 3);
v70 = add(v69, 2);
v71 = add(v70, 1);
add(v71, 20);
v72 = add(&v120[18], 7);
v73 = add(v72, 2);
v74 = add(v73, 4);
v75 = add(v74, 3);
v76 = add(v75, 6);
v77 = add(v76, 5);
v78 = add(v77, 1);
add(v78, 20);
v79 = mul(&v120[19], 1000000);
v80 = sub(v79, 999999);
v81 = mul(v80, 4);
v82 = add(v81, 50);
sub(v82, 1);
v83 = sub(&v120[20], 1);
v84 = mul(v83, -294967296);
v85 = add(v84, 49);
sub(v85, 1);
v86 = sub(&v120[21], 1);
v87 = mul(v86, 1000000000);
v88 = add(v87, 54);
v89 = sub(v88, 1);
v90 = add(v89, 1000000000);
sub(v90, 1000000000);
v91 = add(&v120[22], 49);
v92 = sub(v91, 1);
v93 = add(v92, 2);
sub(v93, 1);
v94 = mul(&v120[23], 10);
v95 = sub(v94, 5);
v96 = mul(v95, 8);
v97 = add(v96, 9);
add(v97, 48);
v98 = add(&v120[24], 1);
v99 = add(v98, 3);
v100 = add(v99, 3);
v101 = add(v100, 3);
v102 = add(v101, 6);
v103 = add(v102, 6);
v104 = add(v103, 6);
add(v104, 20);
v105 = add(&v120[25], 55);
v106 = sub(v105, 33);
v107 = add(v106, 44);
v108 = sub(v107, 11);
add(v108, 42);
add(&v120[26], v120[25]);
add(&v120[27], v120[12]);
v109 = v120[27];
v110 = sub(&v120[28], 1);
v111 = add(v110, v109);
sub(v111, 1);
v112 = v120[23];
v113 = sub(&v120[29], 1);
v114 = mul(v113, 1000000);
add(v114, v112);
v115 = v120[27];
v116 = add(&v120[30], 1);
mul(v116, v115);
add(&v120[31], v120[30]);
内容很简单就是对每个字符运算。手工运算得到结果
s = [
(1000000000-999999950)*2, (1+5000000-6666666+1666666+45)*2+5, (1000000000-999999950)*2+2, 1+55-3+4-1, (1000000000-999999950)*2+2,
55-3, (1000000-999975)*4, 1+55-33+44-11, (10-5)*8+9, 1+53,
1+49-2+4-2, (1000000-999999)*4+50, 7+10+32, (10-5)*8+9+48, 55-3,
1+1+2+3+4+5+6+7+20, (10-5)*8+9+48, 1+7+6+5+4+3+2+1+20, 1+7+2+4+3+6+5+1+20, (1000000-999999)*4+50-1,
49-1, 54-1, 1+49-1+2-1, (10-5)*8+9+48, 2+3+3+3+6+6+6+20,
1+55-33+44-11+42, 1+1+55-33+44-11+42, 1+ 7+10+32, 1-1+ 1+ 7+10+32-1, (10-5)*8+9+48,
2*(1+ 7+10+32), 1+2*(1+ 7+10+32)
]
[print(chr(i), end='') for i in s]
#CTF{daf8f4d816261a41a115052O1bb23Ode}
20,re1-100
main里直接给了比较的串,但顺序有变化,在confuseKey里给了排法
bool __cdecl confuseKey(char *szKey, int iKeyLength)
{
......
strncpy(szPart1, szKey + 1, 0xAuLL);
strncpy(szPart2, szKey + 11, 0xAuLL);
strncpy(szPart3, szKey + 21, 0xAuLL);
strncpy(szPart4, szKey + 31, 0xAuLL);
memset(szKey, 0, iKeyLength);
*szKey = 123;
strcat(szKey, szPart3);
strcat(szKey, szPart4);
strcat(szKey, szPart1);
strcat(szKey, szPart2);
szKey[41] = 125;
return 1;
}
排好序,然后把没皮的包裹去掉
正确的排法
daf29f5903 3
4938ae4efd 4
53fc275d81 1
053ed5be8c 2
#{53fc275d81053ed5be8cdaf29f59034938ae4efd}
#53fc275d81053ed5be8cdaf29f59034938ae4efd
21,XCTF 3rd-RCTF-2017_easyre-153
一打开发现什么都没有,怀疑加壳,用upx先去壳。
在main里有比较的串,在lol里有一些算法
v2 = 2 * a1[1];
v3 = a1[4] + a1[5];
v4 = a1[8] + a1[9];
v5 = 2 * a1[12];
v6 = a1[18] + a1[17];
v7 = a1[10] + a1[21];
v8 = a1[9] + a1[25];
return printf("flag_is_not_here"); // "69800876143568214356928753"
还原串。有了前边的经验rctf这个用大写RCTF{}包
a1 = b"69800876143568214356928753"
b = [2 * a1[1], a1[4] + a1[5], a1[8] + a1[9], 2 * a1[12], a1[18] + a1[17], a1[10] + a1[21], a1[9] + a1[25]]
print(bytes(b))
#rhelheg
#RCTF{rhelheg}
22,百越杯2018_crazy
C++写的面向对象的程序。ida翻译得不好。在对象初始化时有比较串,在calculate里有运算方法:两次异或和加
if ( std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::length((char *)this + 16) != 32 )
{
v1 = std::operator<<<std::char_traits<char>>(&std::cout, "Too short or too long");
std::ostream::operator<<(v1, &std::endl<char,std::char_traits<char>>);
exit(-1);
}
for ( i = 0;
i <= (unsigned __int64)std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::length((char *)this + 16);
++i )
{
v2 = (_BYTE *)std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::operator[]((char *)this + 16,i);
*v2 = (*(_BYTE *)std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::operator[]((char *)this + 16, i) ^ 0x50) + 23;
}
for ( j = 0; ; ++j )
{
result = j <= (unsigned __int64)std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::length((char *)this + 16);
if ( !result )
break;
v4 = (_BYTE *)std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::operator[]( (char *)this + 16, j);
*v4 = (*(_BYTE *)std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::operator[]( (char *)this + 16, j) ^ 0x13) + 11;
}
解码(这个很坑,一眼感觉就不对,里边有半个大括号,可是他真是这样):
a = b'327a6c4304ad5938eaf0efb6cc3e53dc'
b = [0]*32
for i,v in enumerate(a):
b[i] = (((v-11)^0x13)-23)^0x50
print(bytes(b))
#flag{tMx~qdstOs~crvtwb~aOba}qddtbrtcd}
23,2019-ISCC_answer_to_everything
程序巨短,是个脑筋急转弯的题。not_the_flag里有几个字母,然后提法里说sha1
__int64 __fastcall not_the_flag(int a1)
{
if ( a1 == 42 )
puts("Cipher from Bill \nSubmit without any tags\n#kdudpeh");
else
puts("YOUSUCK");
return 0LL;
}
算这几个字符的sha1
'''
sha1 得到了一个神秘的二进制文件。寻找文件中的flag,解锁宇宙的秘密。注意:将得到的flag变为flag{XXX}形式提交。
kdudpeh
sha1(kdudpeh)
flag{80ee2a3fe31da904c596d993f7f1de4827c1450a}
'''
24,csaw-ctf-2016-quals_gametime
这个很乱,网上搜了下,发现确实是逆向不了,直接把出错时的跳转nop等他自己出flag
'''
sub_401260
return 后的两个不相符时退出的jz,jnz nop掉
然后运行程序,不要有任何输入
经过一段时间输出后会输出
key is (no5c30416d6cf52638460377995c6a8cf5)
'''
#no5c30416d6cf52638460377995c6a8cf5