首页
论坛
课程
招聘
[原创]2019看雪CTF Q2第六题
2019-6-10 21:16 903

[原创]2019看雪CTF Q2第六题

2019-6-10 21:16
903

此题没有反调试,逻辑也不复杂。

运行界面如下:


IDA F5出来的代码如下

  printf("please enter Serial:");
  scanf(" %s", &bindata);
  if ( strlen((const char *)&bindata) > 0x31 )
    puts("error");
  v7 = (char *)calloc(1u, 0x400u);
  v3 = strlen((const char *)&bindata);
  base64_encode(&bindata, v7, v3);
  v6 = "!NGV%,$h1f4S3%2P(hkQ94==";
  if ( !strcmp("!NGV%,$h1f4S3%2P(hkQ94==", v7) )
    puts("Success");
  else
    puts("Please Try Again");
  free(v7);
  system("pause");
  return 0;

要求输入SN长度不超过0x31,SN经过base64encode计算,要求与"!NGV%,$h1f4S3%2P(hkQ94=="相等。

跟踪base64_encode函数,发现相较于标准base64encode算法修改了2处地方:

1)  将编码表修改为

tuvwxTUlmnopqrs7YZabcdefghij8yz0123456VWXkABCDEFGHIJKLMNOPQRS9+/

2) 将编码后的字符加密处理,函数逻辑即为charEncrypt()

char __cdecl charEncrypt(int data)
{
  int dataa; // [esp+18h] [ebp+8h]

  dataa = aTuvwxtulmnopqr[data];
  if ( dataa > 0x40 && dataa <= 0x5A )
    return 0x9B - dataa;
  if ( dataa > 0x60 && dataa <= 0x7A )
    return dataa - 0x40;
  if ( dataa > 0x2F && dataa <= 0x39 )
    return dataa + 0x32;
  if ( dataa == '+' )
    return 'w';
  if ( dataa == '/' )
    dataa = 'y';
  return dataa;
}

运行下程序,得出字符的加密映射关系

charEncrypt(A)=Z

charEncrypt(B)=Y

charEncrypt(C)=X

charEncrypt(D)=W

charEncrypt(E)=V

charEncrypt(F)=U

charEncrypt(G)=T

charEncrypt(H)=S

charEncrypt(I)=R

charEncrypt(J)=Q

charEncrypt(K)=P

charEncrypt(L)=O

charEncrypt(M)=N

charEncrypt(N)=M

charEncrypt(O)=L

charEncrypt(P)=K

charEncrypt(Q)=J

charEncrypt(R)=I

charEncrypt(S)=H

charEncrypt(T)=G

charEncrypt(U)=F

charEncrypt(V)=E

charEncrypt(W)=D

charEncrypt(X)=C

charEncrypt(Y)=B

charEncrypt(Z)=A

charEncrypt(a)=!

charEncrypt(b)="

charEncrypt(c)=#

charEncrypt(d)=$

charEncrypt(e)=%

charEncrypt(f)=&

charEncrypt(g)='

charEncrypt(h)=(

charEncrypt(i)=)

charEncrypt(j)=*

charEncrypt(k)=+

charEncrypt(l)=,

charEncrypt(m)=-

charEncrypt(n)=.

charEncrypt(o)=/

charEncrypt(p)=0

charEncrypt(q)=1

charEncrypt(r)=2

charEncrypt(s)=3

charEncrypt(t)=4

charEncrypt(u)=5

charEncrypt(v)=6

charEncrypt(w)=7

charEncrypt(x)=8

charEncrypt(y)=9

charEncrypt(z)=:

charEncrypt(0)=b

charEncrypt(1)=c

charEncrypt(2)=d

charEncrypt(3)=e

charEncrypt(4)=f

charEncrypt(5)=g

charEncrypt(6)=h

charEncrypt(7)=i

charEncrypt(8)=j

charEncrypt(9)=k

charEncrypt(+)=w

charEncrypt(/)=y


还原出来的base64编码算法为:

static const char *codes = "tuvwxTUlmnopqrs7YZabcdefghij8yz0123456VWXkABCDEFGHIJKLMNOPQRS9+/";

char charEncrypt(int dataa)
{
	if (dataa > 0x40 && dataa <= 0x5A)
		return 0x9B - dataa;
	if (dataa > 0x60 && dataa <= 0x7A)
		return dataa - 0x40;
	if (dataa > 0x2F && dataa <= 0x39)
		return dataa + 0x32;
	if (dataa == '+')
		return 0x77;
	if (dataa == '/')
		dataa = 0x79;
	return dataa;
}

int base64_encode(const unsigned char *in, unsigned long len,  unsigned char *out)
{
	unsigned long i, len2, leven;
	unsigned char *p;
	/* vunsignedalid output size ? */
	len2 = 4 * ((len + 2) / 3);
	p = out;
	leven = 3 * (len / 3);
	for (i = 0; i < leven; i += 3) {
		*p++ = charEncrypt(codes[in[0] >> 2]);
		*p++ = charEncrypt(codes[((in[0] & 3) << 4) + (in[1] >> 4)]);
		*p++ = charEncrypt(codes[((in[1] & 0xf) << 2) + (in[2] >> 6)]);
		*p++ = charEncrypt(codes[in[2] & 0x3f]);
		in += 3;
	}
	/* Pad it if necessary...  */
	if (i < len) {
		unsigned a = in[0];
		unsigned b = (i + 1 < len) ? in[1] : 0;
		unsigned c = 0;

		*p++ = charEncrypt(codes[a >> 2]);
		*p++ = charEncrypt(codes[((a & 3) << 4) + (b >> 4)]);
		*p++ = (i + 1 < len) ? charEncrypt(codes[((b & 0xf) << 2) + (c >> 6)]) : '=';
		*p++ = '=';
	}

	/* append a NULL byte */
	*p = '\0';

	return p - out;
}

总结

将SN的字符每3个字节分为一组,每个字节占8bit,共24个二进制位;

将转换后的二进制位每6个一组,分为4组;

在每组前面添加两个0,每组由6个变为8个二进制位,总共32个二进制位,即四个字节;

根据编码表”tuvwxTUlmnopqrs7YZabcdefghij8yz0123456VWXkABCDEFGHIJKLMNOPQRS9+/”获得对应的值;

根据对应值获取charEncrypt后的数值。


刚开始准备枚举爆破,写了如下程序

char szBuf[17] = "";
char szBufEncode[0x100] = "\0";

for(char x1=0x30;x1<=0x7A;x1++)
for(char x2=0x30;x2<=0x7A;x2++)
for (char x3 = 0x30; x3 <= 0x7A; x3++)
for (char x4 = 0x30; x4 <= 0x7A; x4++)
for (char x5 = 0x30; x5 <= 0x7A; x5++)
for (char x6 = 0x30; x6 <= 0x7A; x6++)
for (char x7 = 0x30; x7 <= 0x7A; x7++)
for (char x8 = 0x30; x8 <= 0x7A; x8++)
for (char x9 = 0x30; x9 <= 0x7A; x9++)
for (char x10 = 0x30; x10 <= 0x7A; x10++)
for (char x11 = 0x30; x11 <= 0x7A; x11++)
for (char x12 = 0x30; x12 <= 0x7A; x12++)
for (char x13 = 0x30; x13 <= 0x7A; x13++)
for (char x14 = 0x30; x14 <= 0x7A; x14++)
for (char x15 = 0x30; x15 <= 0x7A; x15++)
for (char x16 = 0x30; x16 <= 0x7A; x16++)
{
	szBuf[0] = x1;
	szBuf[1] = x2;
	szBuf[2] = x3;
	szBuf[3] = x4;
	szBuf[4] = x5;
	szBuf[5] = x6;
	szBuf[6] = x7;
	szBuf[7] = x8;
	szBuf[8] = x9;
	szBuf[9] = x10;
	szBuf[10] = x11;
	szBuf[11] = x12;
	szBuf[12] = x13;
	szBuf[13] = x14;
	szBuf[14] = x15;
	szBuf[15] = x16;

	printf("%s\n", szBuf);

	base64_encode(szBuf, 16, szBufEncode);

	if (!strcmp("!NGV%,$h1f4S3%2P(hkQ94==", szBufEncode))
	{
		printf("the Flag is %s", szBuf);
		break;
	}
}

运行了很久也没跑出来,心急之下笔算出结果

SN=”KanXue2019ctf_st”


[看雪官方培训] Unicorn Trace还原Ollvm算法!《安卓高级研修班》2021年6月班开始招生!!

收藏
点赞0
打赏
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回