实验吧-1

证明自己吧

ida打开,定位到关键函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
  v5 = dword_40708C;
v6 = dword_407090;
v8 = word_407098;
v9 = byte_40709A;
v7 = dword_407094;
if ( strlen(a1) == strlen((const char *)&v5) )
{
v1 = 0;
if ( strlen(a1) != 0 )
{
do
a1[v1++] ^= 0x20u;
while ( v1 < strlen(a1) );
}
v2 = 0;
if ( strlen((const char *)&v5) != 0 )
{
do
*((_BYTE *)&v5 + v2++) -= 5;
while ( v2 < strlen((const char *)&v5) );
}
v3 = 0;
if ( strlen((const char *)&v5) == 0 )
return 1;
while ( *((_BYTE *)&v5 + v3 + a1 - (const char *)&v5) == *((_BYTE *)&v5 + v3) )
{
if ( ++v3 >= strlen((const char *)&v5) )
return 1;
}
}
return 0;
}

可知flag的长度和v5相等,flag每位与0x20异或,v5每位减5之后,flag[i]=v5[i]。

逆运算脚本如下:

1
2
3
4
5
6
7
8
v5=[0x68,0x57,0x19,0x48,0x50,0x6e,0x58,0x78,0x54,0x6a,0x19,0x58,0x5e,6]
temp=[]
for i in v5:
i-=5
i^=0x20
key.append(i)
flag=''.join([chr(i) for i in temp])
print flag

NSCTF Reverse 500

pyc文件直接在线反编译一波:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
data = "M,\x1d-\x18}E'\x1ezN~\x1b*\x19+\x12%\x1d-" + 'I\x7fM(I{I\x7fJ.\x16wWcRj\x0e6\x0fn' + 'Zo\nn\x0fk\t1R7\x03g\x067\x00eUb\x043' + '\x014\x071Rr\x14x\x19~D?q"a5s,A%' + "\x10'\x11uLyA%\x1d|DrFv\x12t\x11#B&" + 'GsKzK*O)\x1c%GuC>\x1e\x7f\x1b+\x19*' + '\x1e&\x14-\x1f/\x1axAqBq@yO-LtE}' + '\x1b,MuBp\x12'
import os
import sys
import struct
import cStringIO
import string
import dis
import marshal
import types
import random
count = 0

def reverse(string):
return string[::-1]

data_list = list(reverse(data)[1:])

def decrpyt(c, key2):
global count
data_list[count] = c ^ key2
count += 1


def GetFlag1():
key = struct.unpack('B', data[len(data) - 8])[0]
for c in data_list:
if count == 0:
decrpyt(struct.unpack('B', c)[0], key)
continue
key = struct.unpack('B', data[len(data) - 3])[0]
decrpyt(struct.unpack('B', c)[0], key)

for c in data_list[::-1]:
print chr(c),



def GetFlag2():
key = struct.unpack('B', data[len(data) - 11])[0]
for c in data_list:
if count == 0:
decrpyt(struct.unpack('B', c)[0], key)
continue
key = struct.unpack('B', data[len(data) - 4 - count])[0]
decrpyt(struct.unpack('B', c)[0], key)

for c in data_list[::-1]:
print chr(c),



def GetFlag3():
key = struct.unpack('B', data[len(data) - 5])[0]
for c in data_list:
if count == 0:
decrpyt(struct.unpack('B', c)[0], key)
continue
key = struct.unpack('B', data[len(data) - 2 - count])[0]
decrpyt(struct.unpack('B', c)[0], key)

for c in data_list[::-1]:
print chr(c),



def GetFlag4():
global count
key = struct.unpack('B', data[len(data) - 1])[0]
for c in data_list:
if count == 0:
decrpyt(struct.unpack('B', c)[0], key)
continue
key = struct.unpack('B', data[len(data) - 1 - count])[0]
decrpyt(struct.unpack('B', c)[0], key)

count = 0
for c in data_list[::-1]:
print chr(c),



def GetFlag5():
key = struct.unpack('B', data[len(data) - 9])[0]
for c in data_list:
if count == 0:
decrpyt(struct.unpack('B', c)[0], key)
continue
key = struct.unpack('B', data[len(data) - 3 - count])[0]
decrpyt(struct.unpack('B', c)[0], key)
for c in data_list[::-12]:
print chr(c),


GetFlag1()

直接运行一波,发现会对data进行报错,百度后发现时在反编译时,例如0f aa这样的指令时会变成\xfa\xa*这样,就会导致错位⽽而解不出flag。

这时可以用winhex打开pyc文件,找到data,然后自己进行转换就行了,data用十六进制表示为:

1
4D2C1D2D 187D4527 1E7A4E7E 1B2A192B 12251D2D 73140000 00497F4D 28497B49 7F4A2E16 77576352 6A0E360F 6E731400 00005A6F 0A6E0F6B 09315237 03670637 00655562 04337314 00000001 34073152 72147819 7E443F71 22613573 2C412573 14000000 10271175 4C794125 1D7C4472 46761274 11234226 73140000 0047734B 7A4B2A4F 291C2547 75433E1E 7F1B2B19 2A731400 00001E26 142D1F2F 1A784171 42714079 4F2D4C74 457D7307 0000001B 2C4D7542 7012

然而运行后得不到flag,不过这里定义了5个getflag函数,一个个尝试后在getflag4时找到了flag。

NSCTF Reverse 400

py2exe的逆向,参考PyInstaller Extractor安装和使用方法

在reverse03里找到了一些代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22


data=\"\x1c\x7a\x16\x77\x10\x2a\x51\x1f\x4c\x0f\x5b\x1d\x42\x2f\x4b\x7e\x4a\x7a\x4a\x7b"+\"\x49\x7f\x4a\x7f\x1e\x78\x4c\x75\x10\x28\x18\x2b\x48\x7e\x46\x23\x12\x24\x11\x72"+\"\x4b\x2e\x1b\x7e\x4f\x2b\x12\x76\x0b"

'''
char buf[] = "flag:{NSCTF_md5098f6bcd4621d373cade4e832627b4f6}";

int _tmain(int argc, _TCHAR* argv[])
{
printf("%d\n", strlen(buf));
char key = '\x0b';
buf[47] ^= key;
for (int i = 1; i < 48; i++)
{
buf[48 - i - 1] ^= buf[48 - i];
}

return 0;
}
'''

print "Revese it?????????"

直接就给出了flag,然而并不正确,看来给了一段c的代码是要用到的。

后发现对data进行如c代码的运算后就可以得到flag,逆运算脚本:

1
2
3
4
5
6
7
8

data="\x1c\x7a\x16\x77\x10\x2a\x51\x1f\x4c\x0f\x5b\x1d\x42\x2f\x4b\x7e\x4a\x7a\x4a\x7b"+"\x49\x7f\x4a\x7f\x1e\x78\x4c\x75\x10\x28\x18\x2b\x48\x7e\x46\x23\x12\x24\x11\x72"+"\x4b\x2e\x1b\x7e\x4f\x2b\x12\x76\x0b"
temp=list(data)
for i in range(0,len(temp)-2):
temp[i]=chr(ord(temp[i])^ord(temp[i+1]))
temp[47]=chr(ord(temp[47])^0x0b)
flag=''.join(i for i in temp)
print flag

bin100(ebCTF 2013)

一个掷🎲小游戏,掷出需要的数字就能得到flag。

用od打开,字符串搜索,定位到:

1
2
0040192B     /75 5E         jnz short Dice.0040198B
0040192D . |C74424 04 1F4>mov dword ptr ss:[esp+0x4],Dice.0044421F ; [*] You rolled a three! Good!

可见这里就是判断掷出的🎲是不是需要的数字,如果不是的话,jnz就会使得进程跳到失败,所以把jnz这一句nop掉就可以跳过判断,使程序认为掷出了需要的数字,后面还有四个一样的地方,也nop掉之后f9运行程序,回车掷完🎲之后,f8往下运行就可以得到flag。

该题不简单

一开始没仔细看题目,以为成功登陆就可以得到flag…后来发现是要找到对应用户名hello的注册码,还是用ida打开看看吧。

文本搜索一下无效,找到了关键函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
String[0] = 0;
memset(&String[1], 0, 0x1Cu);
v3 = 0;
v4 = 0;
String1 = 0;
memset(&v10, 0, 0x1Cu);
v11 = 0;
v12 = 0;
String2 = 0;
memset(&v6, 0, 0x1Cu);
v7 = 0;
v8 = 0;
if ( GetDlgItemTextA(hDlg, 1000, String, 16) < 5 )
return 1;
GetDlgItemTextA(hDlg, 1001, &String1, 16);
v1 = 0;
if ( strlen(String) != 0 )
{
do
{
*(&String2 + v1) = (v1 + v1 * String[v1] * String[v1]) % 0x42 + 33;
++v1;
}
while ( v1 < strlen(String) );
}
strcpy(String, "Happy@");
lstrcatA(String, &String2);
return lstrcmpA(&String1, String) != 0;

如果这个函数返回1的话就是注册码正确了。
输入用户名后,注册码[i]=i+i*用户名[i]*用户名[i]%0x42+33,再在前面加上Happy@就得到注册码了。

脚本如下:

1
2
3
4
5
username="hello"
string2=""
for i in range(len(username)):
string2+=chr(i+i*ord(username[i])*ord(username[i])%0x42 +33)
print "Happy@"+string2

这样的明文密码用od调试应该会更快一点,可以直接看到注册码是什么。

文章目录
  1. 1. 证明自己吧
  2. 2. NSCTF Reverse 500
  3. 3. NSCTF Reverse 400
  4. 4. bin100(ebCTF 2013)
  5. 5. 该题不简单
|