私が集めたものを投稿しています。
一般的な考え方:
- 現在のユーザーアカウントのラージ・ページを有効にします。 (管理者権限が必要です)。
- 現在のプロセストークンに大きなページを有効にします。 (管理者権限が必要です)。
- メモリを割り当てます(実際は2Mbの大きなページサイズに細分化されています)。
あなたはUAC properly disabledお持ちの場合は、管理者権限で一度だけステップ1を実行する必要があります。 UACを有効にしている場合、管理者権限ですべてを実行する必要があります。
#define UNICODE
#define _UNICODE
#include <windows.h>
#include <ntsecapi.h>
#include <ntstatus.h>
#include <Sddl.h>
void InitLsaString(PLSA_UNICODE_STRING LsaString, LPWSTR String)
{
DWORD StringLength;
if (String == NULL) {
LsaString->Buffer = NULL;
LsaString->Length = 0;
LsaString->MaximumLength = 0;
return;
}
StringLength = wcslen(String);
LsaString->Buffer = String;
LsaString->Length = (USHORT)StringLength * sizeof(WCHAR);
LsaString->MaximumLength = (USHORT)(StringLength + 1) * sizeof(WCHAR);
}
NTSTATUS OpenPolicy(LPWSTR ServerName, DWORD DesiredAccess, PLSA_HANDLE PolicyHandle)
{
LSA_OBJECT_ATTRIBUTES ObjectAttributes;
LSA_UNICODE_STRING ServerString;
PLSA_UNICODE_STRING Server = NULL;
//
// Always initialize the object attributes to all zeroes.
//
ZeroMemory(&ObjectAttributes, sizeof(ObjectAttributes));
if (ServerName != NULL) {
//
// Make a LSA_UNICODE_STRING out of the LPWSTR passed in
//
InitLsaString(&ServerString, ServerName);
Server = &ServerString;
}
//
// Attempt to open the policy.
//
return LsaOpenPolicy(
Server,
&ObjectAttributes,
DesiredAccess,
PolicyHandle
);
}
NTSTATUS SetPrivilegeOnAccount(LSA_HANDLE PolicyHandle, PSID AccountSid, LPWSTR PrivilegeName, BOOL bEnable)
{
LSA_UNICODE_STRING PrivilegeString;
//
// Create a LSA_UNICODE_STRING for the privilege name.
//
InitLsaString(&PrivilegeString, PrivilegeName);
//
// grant or revoke the privilege, accordingly
//
if (bEnable) {
return LsaAddAccountRights(
PolicyHandle, // open policy handle
AccountSid, // target SID
&PrivilegeString, // privileges
1 // privilege count
);
}
else {
return LsaRemoveAccountRights(
PolicyHandle, // open policy handle
AccountSid, // target SID
FALSE, // do not disable all rights
&PrivilegeString, // privileges
1 // privilege count
);
}
}
void main()
{
HANDLE hToken = NULL;
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
{
applog(LOG_INFO, "OpenProcessToken failed. GetLastError returned: %d\n", GetLastError());
return -1;
}
DWORD dwBufferSize = 0;
// Probe the buffer size reqired for PTOKEN_USER structure
if (!GetTokenInformation(hToken, TokenUser, NULL, 0, &dwBufferSize) &&
(GetLastError() != ERROR_INSUFFICIENT_BUFFER))
{
applog(LOG_INFO, "GetTokenInformation failed. GetLastError returned: %d\n", GetLastError());
// Cleanup
CloseHandle(hToken);
hToken = NULL;
return -1;
}
PTOKEN_USER pTokenUser = (PTOKEN_USER) malloc(dwBufferSize);
// Retrieve the token information in a TOKEN_USER structure
if (!GetTokenInformation(
hToken,
TokenUser,
pTokenUser,
dwBufferSize,
&dwBufferSize))
{
applog(LOG_INFO, "GetTokenInformation failed. GetLastError returned: %d\n", GetLastError());
// Cleanup
CloseHandle(hToken);
hToken = NULL;
return -1;
}
// Print SID string
LPWSTR strsid;
ConvertSidToStringSid(pTokenUser->User.Sid, &strsid);
applog(LOG_INFO, "User SID: %S\n", strsid);
// Cleanup
CloseHandle(hToken);
hToken = NULL;
NTSTATUS status;
LSA_HANDLE policyHandle;
if (status = OpenPolicy(NULL, POLICY_CREATE_ACCOUNT | POLICY_LOOKUP_NAMES, &policyHandle))
{
applog(LOG_INFO, "OpenPolicy %d", status);
}
// Add new privelege to the account
if (status = SetPrivilegeOnAccount(policyHandle, pTokenUser->User.Sid, SE_LOCK_MEMORY_NAME, TRUE))
{
applog(LOG_INFO, "OpenPSetPrivilegeOnAccountolicy %d", status);
}
// Enable this priveledge for the current process
hToken = NULL;
TOKEN_PRIVILEGES tp;
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, &hToken))
{
applog(LOG_INFO, "OpenProcessToken #2 failed. GetLastError returned: %d\n", GetLastError());
return -1;
}
tp.PrivilegeCount = 1;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
if (!LookupPrivilegeValue(NULL, SE_LOCK_MEMORY_NAME, &tp.Privileges[0].Luid))
{
applog(LOG_INFO, "LookupPrivilegeValue failed. GetLastError returned: %d\n", GetLastError());
return -1;
}
BOOL result = AdjustTokenPrivileges(hToken, FALSE, &tp, 0, (PTOKEN_PRIVILEGES)NULL, 0);
DWORD error = GetLastError();
if (!result || (error != ERROR_SUCCESS))
{
applog(LOG_INFO, "AdjustTokenPrivileges failed. GetLastError returned: %d\n", error);
return -1;
}
// Cleanup
CloseHandle(hToken);
hToken = NULL;
SIZE_T pageSize = GetLargePageMinimum();
// Finally allocate the memory
char *largeBuffer = VirtualAlloc(NULL, pageSize * N_PAGES_TO_ALLOC, MEM_RESERVE | MEM_COMMIT | MEM_LARGE_PAGES, PAGE_READWRITE);
if (largeBuffer)
{
applog(LOG_INFO, "VirtualAlloc failed, error 0x%x", GetLastError());
}
}
あなたは 'MEM_COMMIT'フラグを忘れています。 'VirtualAlloc(NULL、n_bytes、MEM_COMMIT | MEM_LARGE_PAGES、PAGE_READWRITE);'をどのような問題で呼びますか? – RbMm
@RbMmが修正されました。とにかく、私はそれを呼び出す前に、ユーザーアカウントの 'SeLockMemoryPrivilege'特典を取得する必要がありますhttps://msdn.microsoft.com/en-us/library/windows/desktop/aa366720(v=vs.85).aspx –
はい、必要。 'SeLockMemoryPrivilege'が問題になっていますか? – RbMm