写脚本技术很菜,所以和其他wp相比看起来比较麻烦
笔记是按照当时的题目排序写的,顺序可能有出入
做题是从0开始做起,所以前面部分也会尽可能写的详细一点
只要能记录并且了解到怎么做即可,所以就没有去在意排版
遇到不会的函数尽可能去百度了解
题目:[SUCTF2019]SignIn、相册、[BJDCTF2020]easy、[ACTF新生赛2020]usualCrypt、[MRCTF2020]Transform
26.[SUCTF2019]SignIn
得到的 flag 请包上 flag{} 提交。
查壳,无壳,IDA打开,查看main函数
稍微看了一下,发现用到Pow就觉得不对劲,然后看到了65537,加上gmpz,就猜想是一道RSA题目。
翻阅https://gmplib.org/manual/发现猜想正确
所以得到c,n,e
c = 0xad939ff59f6e70bcbfad406f2494993757eee98b91bc244184a377520d06fc35
n = 103461035900816914121390101299049044413950405173712170434161686539878160984549
e = 65537
首先分解N,用的是http://www.factordb.com
得到
q = 282164587459512124844245113950593348271
p = 366669102002966856876605669837014229419
然后写脚本
import gmpy2
import binascii
c = 0xad939ff59f6e70bcbfad406f2494993757eee98b91bc244184a377520d06fc35
n = 103461035900816914121390101299049044413950405173712170434161686539878160984549
e = 65537
q = 282164587459512124844245113950593348271
p = 366669102002966856876605669837014229419
L = (q-1)*(p-1)
d = gmpy2.invert(e,L)
m = gmpy2.powmod(c,d,n)
print(binascii.unhexlify(hex(m)[2:]))
得到flag
flag{Pwn_@_hundred_years}
27.相册
你好,这是上次聚会相片,你看看(病毒,不建议安装到手机,提取完整邮箱即为flag) 注意:得到的 flag 请包上 flag{} 提交
apk逆向,GDA打开,不会em,以后学了补充。
28.[BJDCTF2020]easy
得到的 flag 请包上 flag{} 提交。来源:https://github.com/BjdsecCA/BJDCTF2020
IDA打开,看main函数
运行一下
应该在别的函数里,首先看的就是main函数上面的ques,看了之后感觉挺像的,先从这入手
int ques()
{
int v0; // edx
int result; // eax
int v2[50]; // [esp+20h] [ebp-128h]
int v3; // [esp+E8h] [ebp-60h]
int v4; // [esp+ECh] [ebp-5Ch]
int v5; // [esp+F0h] [ebp-58h]
int v6; // [esp+F4h] [ebp-54h]
int v7; // [esp+F8h] [ebp-50h]
int v8; // [esp+FCh] [ebp-4Ch]
int v9; // [esp+100h] [ebp-48h]
int v10; // [esp+104h] [ebp-44h]
int v11; // [esp+108h] [ebp-40h]
int v12; // [esp+10Ch] [ebp-3Ch]
int j; // [esp+114h] [ebp-34h]
__int64 v14; // [esp+118h] [ebp-30h]
int v15; // [esp+124h] [ebp-24h]
int v16; // [esp+128h] [ebp-20h]
int i; // [esp+12Ch] [ebp-1Ch]
v3 = 2147122737;
v4 = 140540;
v5 = -2008399303;
v6 = 141956;
v7 = 139457077;
v8 = 262023;
v9 = -2008923597;
v10 = 143749;
v11 = 2118271985;
v12 = 143868;
for ( i = 0; i <= 4; ++i )
{
memset(v2, 0, sizeof(v2));
v16 = 0;
v15 = 0;
v0 = *(&v4 + 2 * i);
LODWORD(v14) = *(&v3 + 2 * i);
HIDWORD(v14) = v0;
while ( SHIDWORD(v14) > 0 || v14 >= 0 && (_DWORD)v14 )
{
v2[v16++] = ((SHIDWORD(v14) >> 31) ^ (((unsigned __int8)(SHIDWORD(v14) >> 31) ^ (unsigned __int8)v14)
- (unsigned __int8)(SHIDWORD(v14) >> 31)) & 1)
- (SHIDWORD(v14) >> 31);
v14 /= 2LL;
}
for ( j = 50; j >= 0; --j )
{
if ( v2[j] )
{
if ( v2[j] == 1 )
{
putchar('*');
++v15;
}
}
else
{
putchar(' ');
++v15;
}
if ( !(v15 % 5) )
putchar(' ');
}
result = putchar(10);
}
return result;
}
可以发现,最后的时候会在指定位置分别打印空格和*号,根据Can you find me,可以知道我们需要想办法进入ques函数
用OD,改time的地址为ques的地址(因为time没啥用)
flag{HACKIT4FUN}
29.[ACTF新生赛2020]usualCrypt
得到的 flag 请包上 flag{} 提交。
(题目名字是crypt,文件名字叫base,先猜测一波换表base)
查壳,发现无壳
IDA打开,找到main函数,F5大法
首先查看第一个while,双击byte_40E0E4
……结果显而易见了,换表base和密文都给了,尝试解码,但是发现解不出来(啊这)
去研究一下main函数,之前进入的函数是判断函数,所以这次进入sub_401080加密函数
int __cdecl sub_401080(int a1, int a2, int a3)
{
int v3; // edi
int v4; // esi
int v5; // edx
int v6; // eax
int v7; // ecx
int v8; // esi
int v9; // esi
int v10; // esi
int v11; // esi
_BYTE *v12; // ecx
int v13; // esi
int v15; // [esp+18h] [ebp+8h]
v3 = 0;
v4 = 0;
sub_401000();
v5 = a2 % 3;
v6 = a1;
v7 = a2 - a2 % 3;
v15 = a2 % 3;
if ( v7 > 0 )
{
do
{
LOBYTE(v5) = *(_BYTE *)(a1 + v3);
v3 += 3;
v8 = v4 + 1;
*(_BYTE *)(v8++ + a3 - 1) = byte_40E0A0[(v5 >> 2) & 0x3F];
*(_BYTE *)(v8++ + a3 - 1) = byte_40E0A0[16 * (*(_BYTE *)(a1 + v3 - 3) & 3)
+ (((signed int)*(unsigned __int8 *)(a1 + v3 - 2) >> 4) & 0xF)];
*(_BYTE *)(v8 + a3 - 1) = byte_40E0A0[4 * (*(_BYTE *)(a1 + v3 - 2) & 0xF)
+ (((signed int)*(unsigned __int8 *)(a1 + v3 - 1) >> 6) & 3)];
v5 = *(_BYTE *)(a1 + v3 - 1) & 0x3F;
v4 = v8 + 1;
*(_BYTE *)(v4 + a3 - 1) = byte_40E0A0[v5];
}
while ( v3 < v7 );
v5 = v15;
}
if ( v5 == 1 )
{
LOBYTE(v7) = *(_BYTE *)(v3 + a1);
v9 = v4 + 1;
*(_BYTE *)(v9 + a3 - 1) = byte_40E0A0[(v7 >> 2) & 0x3F];
v10 = v9 + 1;
*(_BYTE *)(v10 + a3 - 1) = byte_40E0A0[16 * (*(_BYTE *)(v3 + a1) & 3)];
*(_BYTE *)(v10 + a3) = 61;
LABEL_8:
v13 = v10 + 1;
*(_BYTE *)(v13 + a3) = 61;
v4 = v13 + 1;
goto LABEL_9;
}
if ( v5 == 2 )
{
v11 = v4 + 1;
*(_BYTE *)(v11 + a3 - 1) = byte_40E0A0[((signed int)*(unsigned __int8 *)(v3 + a1) >> 2) & 0x3F];
v12 = (_BYTE *)(v3 + a1 + 1);
LOBYTE(v6) = *v12;
v10 = v11 + 1;
*(_BYTE *)(v10 + a3 - 1) = byte_40E0A0[16 * (*(_BYTE *)(v3 + a1) & 3) + ((v6 >> 4) & 0xF)];
*(_BYTE *)(v10 + a3) = byte_40E0A0[4 * (*v12 & 0xF)];
goto LABEL_8;
}
LABEL_9:
*(_BYTE *)(v4 + a3) = 0;
return sub_401030((const char *)a3);
}
首先查看sub_401000函数
其中,byte_40E0AA是
KLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/
byte_40E0A0是
ABCDEFGHIJ
研究此循环,发现是将表中QRSTUVWXY和GHIJKLMNO进行了交换
(因为可以将此表拼接起来成为ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/ 然后又分开看,可以发现40E0AA是从K开始,40E0A0是从A开始,所以是这样换的表)
手动替换一下
ABCDEFQRSTUVWXYPGHIJKLMNOZabcdefghijklmnopqrstuvwxyz0123456789+/
然后吧,中间就是base过程,但是最后有个函数(sub_401030)
明显的大小写转换,在线转一下
string = 'zMXHz3TIgnxLxJhFAdtZn2fFk3lYCrtPC2l9'.swapcase() #sub_401030()
print (string)
得到之后再在线换表转一下
flag{bAse64_h2s_a_Surprise}
30.[MRCTF2020]Transform
得到的 flag 请包上 flag{} 提交。
感谢天璇战队供题。
天璇战队平台:http://ctf.merak.codes/
IDA64
要求长度33,然后进入循环,最后进行判断
判断是将byte_40E640与byte_414040进行判断,v6是我们输入的flag,在循环里会将其打乱之后赋值给byte_414040,然后byte_414040与我们输入的flag进行异或,现在已经给出了异或之后的值(byte_40F0E0中),可以写脚本了
enc = [103, 121, 123, 127, 117, 43, 60, 82, 83, 121, 87, 94, 93, 66, 123, 45, 42, 102, 66, 126, 76, 87, 121, 65, 107, 126, 101, 60, 92, 69, 111, 98, 77]#3F dup(0)是3F是0的意思
chg = [9, 10, 15, 23, 7, 24, 12, 6, 1, 16, 3, 17, 32, 29, 11,30, 27, 22, 4, 13, 19, 20, 21, 2, 25, 5, 31, 8, 18,26, 28, 14,0] #同理8 dup(0)是8个0的意思
tmp = ''
flag = ['']*len(enc)
for i in range(len(enc)):
tmp += chr(enc[i]^chg[i]) #byte_414040
#print(tmp)
for i in range(len(tmp)):
flag[chg[i]] += chr(ord(tmp[i]))
print(''.join(flag))
flag{Tr4nsp0sltiON_Clph3r_1s_3z}