造轮子记
2022-2-18 01:2:10 Author: 0range-x.github.io(查看原文) 阅读量:52 收藏

博客好长时间没更了,就把这段时间做的一点事情记录下吧。尝试第一次造轮子,写个xshell的密码读取工具(公司没有逼迫我qaq)。也挺好,有点压力也有动力,中间好多次想放弃。c语言实在是太太太太麻烦了。有了bug得扣内存去调试,解密出来乱码了也要读内存。头大。另外只是读取xshell6的密码,7的话用ida简单看了下,没找到加密函数,遂放弃。(我太菜了)

1
2
3
读取并不难,密码不是明文传输,而是加密后的,解密的操作也浪费了很长时间。
如果存在 .xsh 文件 读取其中内容
解密条件: 当前用户的username和sid (whoami /user) 、xsh中的password密码
1
2
3
xshell7:    %userprofile%\Documents\NetSarang Computer\7\Xshell\Sessions
xshell6: %userprofile%\Documents\NetSarang Computer\6\Xshell\Sessions
XShell5: %userprofile%\Documents\NetSarang\Xshell\Sessions
1
2
username+sid -> key   
sha256("初始密码") ->CheckSum

Xshell 使用 MD5 算法来生成用于 RC4 密码的密钥,且 使用 16 字节长的 ASCII 字符串 MD5 摘要[email protected]#h$e%l^l&作为 RC4 密码密钥

1
2
3
4
5

unsigned char Key[16] = {
0xba, 0x2d, 0x9b, 0x7e, 0x9c, 0xca, 0x73, 0xd1,
0x52, 0xb2, 0x67, 0x72, 0x66, 0x2d, 0xf5, 0x5e
};
1
2
3
4
5
6
7
8
9
10
11
For example, if your current OS account's SID string is

S-1-5-21-917267712-1342860078-1792151419-512
the 32-bytes-long SHA-256 digest would be

unsigned char Key[32] = {
0xCE, 0x97, 0xBE, 0xA9, 0x0C, 0x2A, 0x40, 0xB9,
0x5C, 0xC0, 0x79, 0x74, 0x1D, 0xDC, 0x03, 0xCB,
0x39, 0xAB, 0x3D, 0xE5, 0x26, 0x7A, 0x3B, 0x11,
0x05, 0x4B, 0x96, 0x3C, 0x93, 0x6F, 0x9C, 0xD4
};

这种情况与前一种(版本 5.1 或 5.2)类似,密钥是当前操作系统帐户名称(区分大小写)和当前操作系统帐户的 SID 字符串组合的 SHA-256 摘要。例如,如果您当前的操作系统帐户的名称和 SID 是(注意是当前登陆用户哈) Administrator S-1-5-21-917267712-1342860078-1792151419-512 密钥是字符串的 32 字节长 SHA-256 摘要”AdministratorS-1-5-21-917267712-1342860078-1792151419-512”

1
2
3
4
5
6
7
8
9
10
11
12
For example, if your current OS account's name and SID are

Administrator
S-1-5-21-917267712-1342860078-1792151419-512
the key is the 32-bytes-long SHA-256 digest of a string "AdministratorS-1-5-21-917267712-1342860078-1792151419-512":

unsigned char Key[32] = {
0x8E, 0x12, 0x29, 0xDC, 0x1F, 0x34, 0x56, 0xB9,
0xBB, 0xCD, 0x94, 0xC2, 0xAB, 0x0A, 0xF3, 0xB9,
0x95, 0x96, 0x6F, 0x06, 0xE3, 0x9D, 0x24, 0x80,
0x6A, 0x74, 0xCD, 0x7E, 0x0B, 0x69, 0xB3, 0x78
};
1
2
3
4
5
6
7
8
For example, if I set master password with "123123", the key that is used in RC4 cipher is

unsigned char Key[32] = {
0x96, 0xca, 0xe3, 0x5c, 0xe8, 0xa9, 0xb0, 0x24,
0x41, 0x78, 0xbf, 0x28, 0xe4, 0x96, 0x6c, 0x2c,
0xe1, 0xb8, 0x38, 0x57, 0x23, 0xa9, 0x6a, 0x6b,
0x83, 0x88, 0x58, 0xcd, 0xd6, 0xca, 0x0a, 0x1e
};
1
2
3
4
5
6
7
8
如果原密码是 "This is a test", the SHA-256 digest would be:

unsigned char Checksum[32] = {
0xC7, 0xBE, 0x1E, 0xD9, 0x02, 0xFB, 0x8D, 0xD4,
0xD4, 0x89, 0x97, 0xC6, 0x45, 0x2F, 0x5D, 0x7E,
0x50, 0x9F, 0xBC, 0xDB, 0xE2, 0x80, 0x8B, 0x16,
0xBC, 0xF4, 0xED, 0xCE, 0x4C, 0x07, 0xD1, 0x4E
};
1
2
3
4
unsigned  char EncryptedPassword[] = {
0x84 , 0x83 , 0x31 , 0x23 , 0x24 , 0x37 , 0x1D , 0xB2 ,
0x6C , 0x54 , 0x87 , 0x5B , 0x6E , 0xE9
};
1
2
3
4
unsigned  char EncryptedPassword[] = {
0xCE , 0xFD , 0xB5 , 0x3B , 0x5C , 0x78 , 0xDE , 0xA4 ,
0x6C , 0xDD , 0xCE , 0x4D , 0x72 , 0x40
};
1
2
3
4
unsigned  char EncryptedPassword[] = {
0x46 , 0xb9 , 0xb7 , 0x3f , 0x70 , 0x0b , 0xd2 , 0x20 ,
0xd5 , 0xee , 0x70 , 0x5b , 0x4b , 0x66
};
1
2
3
4
5
6
7
8
 unsigned char FinalResult [ ] =
{ 0x84,0x83,0x31,0x23,0x24,0x37,0x1d,0xb2,0x6c,0x54,0x87,0x5b,0x0,0xe9,0xc7,0xbe,0x1e,0xD9,0x02,0xFB,0x8D,0xD4 _ _
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _
_ _ _ _ _ _ , 0xD4 , 0x89 ,
0x97,0xC6,0x45,0x2f,0x5d,0x7e,0x50,0x9f,0xbc,0xdb,0xe2,0x80,0x8b,
0x16,0xbc,0xf4,0xed,0xce,0x4c,0x07,0xd1,0x4e }
; _ _ _ _ _ _ _ _ _
_ _ _ _ _ _ _ _ _ _
1
2
3
4
5
6
7
8
 unsigned char FinalResult [ ] = {
0xCE,0xFD,0xB5,0x3b,0x5c,
0x78,0xDE,0xA4,0x6c,0xdd,0xce,0x4d,0x72,0x40,0xc7,0xbe,0x1e,0xD9,0x02,0xFB,0x8D,0xD4 _ _ _ _ _ _
_ _ _ _ _ , 0xD4 , 0x89 ,
0x97,0xC6,0x45,0x2f,0x5d,0x7e,0x50,0x9f,0xbc,0xdb,0xe2,0x80,0x8b,
0x16,0xbc,0xf4,0xed,0xce,0x4c,0x07,0xd1,0x4e }
; _ _ _ _ _ _ _ _ _
_ _ _ _ _ _ _ _ _ _
1
2
3
4
5
6
7
8
 unsigned char finalresult [ ] =
{ 0x46,0xb9,0xb7,0x3f,0x70,0x0b,0xd2,0x20,0xd5,0xee,0x70,0x5b,0x4b,0x66,0xc7,0xbe,0x1e,
0xD9,0x02,0xFB,0x8D,0xD4 _ _ _ _ _ _ _ _ _ _ _ _ _ _
_ _ _ _ _ , 0xD4 , 0x89 ,
0x97,0xC6,0x45,0x2f,0x5d,0x7e,0x50,0x9f,0xbc,0xdb,0xe2,0x80,0x8b,
0x16,0xbc,0xf4,0xed,0xce,0x4c,0x07,0xd1,0x4e }
; _ _ _ _ _ _ _ _ _
_ _ _ _ _ _ _ _ _ _
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
char* Getsid();

LPWSTR wSid = NULL;
TCHAR UserName[64], DomainName[64];

char* Getsid() {
HANDLE hToken;
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &hToken))
{
printf("[!]OpenProcessToken error\n");
return 0;
}

DWORD Size, UserSize, DomainSize;
SID* sid;
SID_NAME_USE SidType;


TOKEN_USER* User;
Size = 0;

GetTokenInformation(hToken, TokenUser, NULL, 0, &Size);
if (!Size)
return 0;

User = (TOKEN_USER*)malloc(Size);
assert(User);
GetTokenInformation(hToken, TokenUser, User, Size, &Size);
assert(Size);
Size = GetLengthSid(User->User.Sid);
assert(Size);
sid = (SID*)malloc(Size);
assert(sid);

CopySid(Size, sid, User->User.Sid);
UserSize = (sizeof UserName / sizeof * UserName) - 1;
DomainSize = (sizeof DomainName / sizeof * DomainName) - 1;
LookupAccountSid(NULL, sid, UserName, &UserSize, DomainName, &DomainSize, &SidType);


int ret = ConvertSidToStringSid(User->User.Sid, &wSid);
if (FAILED(ret)) {
printf("Failed to return ret.");
printf("Error code=0x");
printf("%4x", ret);
}
char* result = strcat(UserName, wSid);
free(sid);
free(User);
return result;
}
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
void find(char* path, char* name)
{
char szFind[MAX_PATH], szFile[MAX_PATH];
WIN32_FIND_DATA fd;
sprintf(szFind, "%s\\%s", path, name);
HANDLE hFind = FindFirstFile(szFind, &fd);
if (INVALID_HANDLE_VALUE != hFind)
{
while (1)
{
char* q = name;
char* p = fd.cFileName;
while (q) {
if (*q == '.')break;
q++;
}
while (p) {
if (*p == '.')break;
p++;
}
if (strncmp(p, q, strlen(q) + 1) != 0) {
if (!FindNextFile(hFind, &fd))break;
continue;
}
int path_len = strlen(path) + strlen(fd.cFileName);

char* tmp_pathname = (char*)malloc(file_Len);
sprintf(tmp_pathname, "%s\\%s", path, fd.cFileName);
path_add(tmp_pathname);

num1++;
if (!FindNextFile(hFind, &fd))break;
}
FindClose(hFind);
}
sprintf(szFind, "%s\\*.*", path);

hFind = FindFirstFile(szFind, &fd);
if (INVALID_HANDLE_VALUE == hFind)return;
while (TRUE)
{
if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
if (fd.cFileName[0] != '.')
{
sprintf(szFile, "%s\\%s", path, fd.cFileName);
find(szFile, name);
}
}
if (!FindNextFile(hFind, &fd))break;
}
FindClose(hFind);
}
1
2
3
4
5
6
7
8
char* become_char(WCHAR* source, int size)
{
char* tmp = (char*)malloc(size / 2 + 1);
WideCharToMultiByte(CP_ACP, 0, source, wcslen(source), tmp, size, NULL, NULL);
tmp[strlen(tmp)] = '\0';
free(source);
return tmp;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
char* getfileall(char* fname, int MODEL)
{
FILE* file = fopen(fname, "rb+");
fpos_t pos = 0;
fgetpos(file, &pos);
fseek(file, 0, SEEK_END);
int filesize = ftell(file);
char* buffer = (char*)malloc(filesize + 1);
memset(buffer, 0, strlen(buffer));
buffer[filesize] = '\0';
fsetpos(file, &pos);
fread(buffer, sizeof(char), filesize, file);
fclose(file);
if (MODEL == WCHAR_MODEL)
{
return become_char(buffer, filesize);
}
else if (MODEL == CHAR_MODEL)
{
return buffer;
}
}
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
char* extract(char* txt, char* name)
{
char* ptr = NULL;
ptr = txt;
int total = 0;

do
{
if (total > 0)
ptr += strlen(name);

ptr = strstr(ptr, name);
if (ptr == NULL)
{
printf("没有找到该字段\n");
return NULL;
}
total++;
} while (*(ptr - 1) != 0x0a);

ptr = ptr + strlen(name) + 1;
int len = get_len(ptr);
char* final = (char*)malloc(len + 1);
memset(final, 0, strlen(final) + 1);
strncat(final, ptr, len);
final[strlen(final) + 1] = '\0';
return final;
}
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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
#define SWAP_BYTES

#ifdef USE_STD_MEMCPY
#include <string.h>
#endif
#include "sha256.h"



#define RL(x,n) (((x) << n) | ((x) >> (32 - n)))
#define RR(x,n) (((x) >> n) | ((x) << (32 - n)))

#define S0(x) (RR((x), 2) ^ RR((x),13) ^ RR((x),22))
#define S1(x) (RR((x), 6) ^ RR((x),11) ^ RR((x),25))
#define G0(x) (RR((x), 7) ^ RR((x),18) ^ ((x) >> 3))
#define G1(x) (RR((x),17) ^ RR((x),19) ^ ((x) >> 10))


#define BSWP(x,y) _bswapw((uint32_t *)(x), (uint32_t)(y))

#define MEMCP(x,y,z) _memcp((x),(y),(z))



static const uint32_t K[64] = {
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
};

static void _bswapw(uint32_t* p, uint32_t i)
{
while (i--) p[i] = (RR(p[i], 24) & 0x00ff00ff) | (RR(p[i], 8) & 0xff00ff00);

}


void* __cdecl _memcp(void* d, const void* s, uint32_t sz)
{
void* rv = d;

while (sz--) *(char*)d = *(char*)s, d = (char*)d + 1, s = (char*)s + 1;

return(rv);
}

static void _rtrf(uint32_t* b, uint32_t* p, uint32_t i, uint32_t j)
{
#define B(x, y) b[(x-y) & 7]
#define P(x, y) p[(x+y) & 15]

B(7, i) += (j ? (p[i & 15] += G1(P(i, 14)) + P(i, 9) + G0(P(i, 1))) : p[i & 15])
+ K[i + j] + S1(B(4, i))
+ (B(6, i) ^ (B(4, i) & (B(5, i) ^ B(6, i))));
B(3, i) += B(7, i);
B(7, i) += S0(B(0, i)) + ((B(0, i) & B(1, i)) | (B(2, i) & (B(0, i) ^ B(1, i))));

#undef P
#undef B
}

static void _hash(sha256_context* ctx)
{
uint32_t b[8], * p, j;

b[0] = ctx->hash[0]; b[1] = ctx->hash[1]; b[2] = ctx->hash[2];
b[3] = ctx->hash[3]; b[4] = ctx->hash[4]; b[5] = ctx->hash[5];
b[6] = ctx->hash[6]; b[7] = ctx->hash[7];

for (p = ctx->buf, j = 0; j < 64; j += 16)
_rtrf(b, p, 0, j), _rtrf(b, p, 1, j), _rtrf(b, p, 2, j),
_rtrf(b, p, 3, j), _rtrf(b, p, 4, j), _rtrf(b, p, 5, j),
_rtrf(b, p, 6, j), _rtrf(b, p, 7, j), _rtrf(b, p, 8, j),
_rtrf(b, p, 9, j), _rtrf(b, p, 10, j), _rtrf(b, p, 11, j),
_rtrf(b, p, 12, j), _rtrf(b, p, 13, j), _rtrf(b, p, 14, j),
_rtrf(b, p, 15, j);

ctx->hash[0] += b[0]; ctx->hash[1] += b[1]; ctx->hash[2] += b[2];
ctx->hash[3] += b[3]; ctx->hash[4] += b[4]; ctx->hash[5] += b[5];
ctx->hash[6] += b[6]; ctx->hash[7] += b[7];

}

void sha256_init(sha256_context* ctx)
{
ctx->len[0] = ctx->len[1] = 0;
ctx->hash[0] = 0x6a09e667; ctx->hash[1] = 0xbb67ae85;
ctx->hash[2] = 0x3c6ef372; ctx->hash[3] = 0xa54ff53a;
ctx->hash[4] = 0x510e527f; ctx->hash[5] = 0x9b05688c;
ctx->hash[6] = 0x1f83d9ab; ctx->hash[7] = 0x5be0cd19;

}

void sha256_hash(sha256_context* ctx, uint8_t* dat, uint32_t sz)
{
register uint32_t i = ctx->len[0] & 63, l, j;

if ((ctx->len[0] += sz) < sz) ++(ctx->len[1]);

for (j = 0, l = 64 - i; sz >= l; j += l, sz -= l, l = 64, i = 0)
{
MEMCP((char*)ctx->buf + i, &dat[j], l);
BSWP(ctx->buf, 16);
_hash(ctx);
}
MEMCP((char*)ctx->buf + i, &dat[j], sz);

}


void sha256_done(sha256_context* ctx, uint8_t* buf)
{
uint32_t i = (uint32_t)(ctx->len[0] & 63), j = ((~i) & 3) << 3;

BSWP(ctx->buf, (i + 3) >> 2);

ctx->buf[i >> 2] &= 0xffffff80 << j;
ctx->buf[i >> 2] |= 0x00000080 << j;

if (i < 56) i = (i >> 2) + 1;
else ctx->buf[15] ^= (i < 60) ? ctx->buf[15] : 0, _hash(ctx), i = 0;

while (i < 14) ctx->buf[i++] = 0;

ctx->buf[14] = (ctx->len[1] << 3) | (ctx->len[0] >> 29);
ctx->buf[15] = ctx->len[0] << 3;

_hash(ctx);

for (i = 0; i < 32; i++)
ctx->buf[i % 16] = 0,
buf[i] = (uint8_t)(ctx->hash[i >> 2] >> ((~i & 3) << 3));

}
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

char* base64_decode(char* code)
{

int table[] = { 0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,62,0,0,0,
63,52,53,54,55,56,57,58,
59,60,61,0,0,0,0,0,0,0,0,
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,0,0,0,0,0,0,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
};
long len;
long str_len;
char* res;
int i, j;


len = strlen(code);

if (strstr(code, "=="))
str_len = len / 4 * 3 - 2;
else if (strstr(code, "="))
str_len = len / 4 * 3 - 1;
else
str_len = len / 4 * 3;

res = (char*)malloc(sizeof(unsigned char) * str_len + 1);
res[str_len] = '\0';


for (i = 0, j = 0; i < len - 2; j += 3, i += 4)
{
res[j] = ((unsigned char)table[code[i]]) << 2 | (((unsigned char)table[code[i + 1]]) >> 4);
res[j + 1] = (((unsigned char)table[code[i + 1]]) << 4) | (((unsigned char)table[code[i + 2]]) >> 2);
res[j + 2] = (((unsigned char)table[code[i + 2]]) << 6) | ((unsigned char)table[code[i + 3]]);
}

return res;

}

一个工具开发了一个多星期,期间几位师傅指导了我很多。暂时不会开源,用完会开源(dddd)。当然这个工具也没啥难度。体会到了改bug的快乐,也希望自己也能早日成为一名coder。明天就回学校了,下一阶段学习应该是免杀为主,但很多东西不能发,哎。希望也能多多输出文章吧。

Peace.


文章来源: https://0range-x.github.io/2022/02/18/xshell%E6%A1%86%E6%9E%B6/
如有侵权请联系:admin#unsafe.sh