SHOW:
|
|
- or go back to the newest paste.
1 | #include <iostream> | |
2 | #include <strsafe.h> | |
3 | #include <wtypes.h> | |
4 | #include <winnt.h> | |
5 | ||
6 | typedef _Return_type_success_(return >= 0) LONG NTSTATUS; | |
7 | #define NT_SUCCESS(Status) (((NTSTATUS)(Status) >= 0)) | |
8 | #define OBJ_CASE_INSENSITIVE 0x00000040L | |
9 | ||
10 | typedef struct _UNICODE_STRING | |
11 | { | |
12 | USHORT Length; | |
13 | USHORT MaximumLength; | |
14 | PWSTR Buffer; | |
15 | } UNICODE_STRING, * PUNICODE_STRING; | |
16 | ||
17 | typedef struct _OBJECT_ATTRIBUTES | |
18 | { | |
19 | ULONG Length; | |
20 | HANDLE RootDirectory; | |
21 | PUNICODE_STRING ObjectName; | |
22 | ULONG Attributes; | |
23 | PVOID SecurityDescriptor; | |
24 | PVOID SecurityQualityOfService; | |
25 | } OBJECT_ATTRIBUTES, * POBJECT_ATTRIBUTES; | |
26 | ||
27 | template< typename modHandleType, typename procNameType > | |
28 | auto getProcAddressOrThrow(modHandleType modHandle, procNameType procName) { | |
29 | auto address = GetProcAddress(modHandle, procName); | |
30 | if (address == nullptr) throw std::exception{ (std::string{"Error importing: "} + (std::string{procName})).c_str() }; | |
31 | return address; | |
32 | } | |
33 | ||
34 | #define CONCAT( id1, id2 ) id1##id2 | |
35 | // Notice- the comma operator is used to make sure the dll is loaded, discard the result- then getModuleHandle is used | |
36 | ||
37 | #define IMPORTAPI( DLLFILE, FUNCNAME, RETTYPE, ... ) \ | |
38 | typedef RETTYPE( WINAPI* CONCAT( t_, FUNCNAME ) )( __VA_ARGS__ ); \ | |
39 | template< typename... Ts > \ | |
40 | auto FUNCNAME( Ts... ts ) { \ | |
41 | const static CONCAT( t_, FUNCNAME ) func = \ | |
42 | (CONCAT( t_, FUNCNAME )) getProcAddressOrThrow( ( LoadLibrary( DLLFILE ), GetModuleHandle( DLLFILE ) ), #FUNCNAME ); \ | |
43 | return func( std::forward< Ts >( ts )... ); \ | |
44 | }; | |
45 | ||
46 | IMPORTAPI(L"ntdll.dll", RtlNtStatusToDosError, NTSTATUS, NTSTATUS ) | |
47 | IMPORTAPI( L"ntdll.dll", NtCreateSymbolicLinkObject, NTSTATUS, PHANDLE , ACCESS_MASK , POBJECT_ATTRIBUTES , PUNICODE_STRING ) | |
48 | ||
49 | void ErrorExit(LPTSTR lpszFunction,NTSTATUS ntstatus) | |
50 | { | |
51 | LPVOID lpMsgBuf; | |
52 | LPVOID lpDisplayBuf; | |
53 | DWORD dw = RtlNtStatusToDosError(ntstatus) ; | |
54 | ||
55 | FormatMessage( | |
56 | FORMAT_MESSAGE_ALLOCATE_BUFFER | | |
57 | FORMAT_MESSAGE_FROM_SYSTEM | | |
58 | FORMAT_MESSAGE_IGNORE_INSERTS, | |
59 | NULL, | |
60 | dw, | |
61 | MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), | |
62 | (LPTSTR)&lpMsgBuf, | |
63 | 0, NULL); | |
64 | ||
65 | lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT, (lstrlen((LPCTSTR)lpMsgBuf) + lstrlen((LPCTSTR)lpszFunction) + 40) * sizeof(TCHAR)); | |
66 | StringCchPrintf( (LPTSTR)lpDisplayBuf, LocalSize(lpDisplayBuf) / sizeof(TCHAR), TEXT("%s failed with error %d: %s"), lpszFunction, dw, lpMsgBuf ); | |
67 | ||
68 | MessageBox(NULL, (LPCTSTR)lpDisplayBuf, TEXT("Error"), MB_OK); | |
69 | ||
70 | LocalFree(lpMsgBuf); | |
71 | LocalFree(lpDisplayBuf); | |
72 | ExitProcess(dw); | |
73 | } | |
74 | ||
75 | int main() | |
76 | { | |
77 | HANDLE SymbolicLinkHandle; | |
78 | UNICODE_STRING dest{ 8, 8, []() { static auto dest = (wchar_t*)L"\\NUL"; return dest; }() }; | |
79 | ||
80 | UNICODE_STRING link{ 28, 28, []() { static auto dest = (wchar_t*)L"\\??\\GLOBALROOT"; return dest; }() }; | |
81 | OBJECT_ATTRIBUTES oa{ sizeof(OBJECT_ATTRIBUTES), 0, &link, OBJ_CASE_INSENSITIVE, nullptr, nullptr }; | |
82 | ||
83 | auto symlink_status = NtCreateSymbolicLinkObject( &SymbolicLinkHandle, MAXIMUM_ALLOWED, &oa, &dest ); | |
84 | if ( ! (NT_SUCCESS(symlink_status))) { ErrorExit((wchar_t*)L"NtCreateSymbolicLinkObject", symlink_status); }; | |
85 | ||
86 | std::cout << "Created \\??\\GLOBALROOT -> \\NUL - Immunity archived" << std::endl; | |
87 | ||
88 | system("pause"); | |
89 | } |