Get device encryption support information - c++

I want to detect the device encryption support in my program. This info is available in the System Information program. Please check out the screenshot below:
What kind of Win API functions are used/available to detect the device encryption support? What System Information program uses to detect it? I just need some information.

TL;DR: it uses undocumented functions from fveapi.dll (Windows Bitlocker Drive Encryption API). It seems to rely only on the TPM capabilities.
Note that I only spent like 15 mins on it, but I doubt I missed something crucial, althoug this might be possible.
A bit of Reverse engineering
Typed system information in search bar, saw it spawned msinfo32.exe. Put the binary in a disassembler. It uses a MUI file so I'll have to search for the strings in the MUI file and not the executable.
Searching Device Encryption Support leads to string ID 951 (0x3b7)
STRINGTABLE
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
{
951, "Device Encryption Support|%s"
Searching for the contant in the disassembler leads to a function named:
DeviceEncryptionDataPoints(struct CWMIHelper *, struct CPtrList *)
The load ing of the aforementioned string is almost right at the start:
.text:00000001400141E9 mov edx, 3B7h
.text:00000001400141EE lea rcx, [rsp+2C8h+var_280]
.text:00000001400141F3
.text:00000001400141F3 loc_1400141F3:
.text:00000001400141F3 ; try {
.text:00000001400141F3 call cs:__imp_?LoadStringW#CString##QEAAHI#Z ; CString::LoadStringW(uint)
So we are definitely in the right function.
It loads the fveapi.dll module:
.text:0000000140014269 xor edx, edx ; hFile
.text:000000014001426B mov r8d, 800h ; dwFlags
.text:0000000140014271 lea rcx, LibFileName ; "fveapi.dll"
.text:0000000140014278 call cs:__imp_LoadLibraryExW
Gets a pointer on FveQueryDeviceEncryptionSupport:
.text:00000001400142AB lea rdx, aFvequerydevice ; "FveQueryDeviceEncryptionSupport"
.text:00000001400142B2 mov rcx, rdi ; hModule
.text:00000001400142B5 call cs:__imp_GetProcAddress
And immediately calls the function (this is a protected CFG call, but it's here):
.text:00000001400142CA mov [rsp+2C8h+var_254], rbx
.text:00000001400142CF mov [rsp+2C8h+var_260], 14h
.text:00000001400142D7 mov [rsp+2C8h+var_25C], 1
.text:00000001400142DF mov [rsp+2C8h+var_258], 1
.text:00000001400142E7 lea rcx, [rsp+2C8h+var_260]
.text:00000001400142EC call cs:__guard_dispatch_icall_fptr
Return value
If the function fails:
.text:00000001400142EC call cs:__guard_dispatch_icall_fptr
.text:00000001400142F2 mov esi, eax
.text:00000001400142F4 test eax, eax
.text:00000001400142F6 js loc_1400143F0 ; check failure
We land here:
.text:00000001400143F7 mov edx, 2FFh
.text:00000001400143FC lea rcx, [rsp+2C8h+var_288]
.text:0000000140014401 call cs:__imp_?LoadStringW#CString##QEAAHI#Z ; CString::LoadStringW(uint)
The string 0x2FF (767) is:
767, "Elevation Required to View"
If the call succeed, the code checks one of the parameter which is definitly an out parameter:
.text:00000001400142EC call cs:__guard_dispatch_icall_fptr
.text:00000001400142F2 mov esi, eax
.text:00000001400142F4 test eax, eax
.text:00000001400142F6 js loc_1400143F0
.text:00000001400142FC cmp dword ptr [rsp+2C8h+var_254], ebx ; rbx = 0
.text:0000000140014300 jnz short loc_14001431D
.text:0000000140014302 mov edx, 3B8h
.text:0000000140014307 lea rcx, [rsp+2C8h+var_288]
.text:000000014001430C call cs:__imp_?LoadStringW#CString##QEAAHI#Z ; CString::LoadStringW(uint)
If it's 0, the string 0x3b8 (952) is used:
952, "Meets prerequisites"
Otherwise various failure functions are called.
Failure
In case of a failure, the UpdateDeviceEncryptionStateFailureString function is called:
.text:0000000140014325 lea r9, [rsp+2C8h+var_294] ; int *
.text:000000014001432A lea r8, [rsp+2C8h+var_290] ; int *
.text:000000014001432F mov edx, 3C1h ; unsigned int
.text:0000000140014334 lea rcx, [rsp+2C8h+var_288] ; struct CString *
.text:0000000140014339 call ?UpdateDeviceEncryptionStateFailureString##YAXPEAVCString##IPEAH1#Z ; UpdateDeviceEncryptionStateFailureString(CString *,uint,int *,int *)
Its main goal is to fetch some string from the resource file.
One that stands out is 0x3b9:
.text:0000000140013A37 mov edx, 3B9h
.text:0000000140013A3C mov rcx, rbx
.text:0000000140013A3F call cs:__imp_?LoadStringW#CString##QEAAHI#Z ; CString::LoadStringW(uint)
953, "Reasons for failed automatic device encryption"
Which is the case for me since I don't have a TPM.
Other Functions
All of the other functions called from the DeviceEncryptionDataPoints (at least to get the needed results) are all from the fveapi.dll.
There are a lot in a function called PerformIndividualHardwareTests(HINSTANCE hModule, struct CString *, int *, int *):
.text:0000000140013AEF lea rdx, aNgscbcheckisao ; "NgscbCheckIsAOACDevice"
.text:0000000140013AF6 mov [rbp+var_1F], 0
.text:0000000140013AFA mov rdi, r9
.text:0000000140013AFD mov [rbp+var_20], 0
.text:0000000140013B01 mov rsi, r8
.text:0000000140013B04 mov [rbp+var_1E], 0
.text:0000000140013B08 mov rbx, rcx
.text:0000000140013B0B call cs:__imp_GetProcAddress
.text:0000000140013B12 nop dword ptr [rax+rax+00h]
.text:0000000140013B17 mov r12, rax
.text:0000000140013B1A test rax, rax
.text:0000000140013B1D jz loc_140013CB9
.text:0000000140013B23 lea rdx, aNgscbcheckishs ; "NgscbCheckIsHSTIVerified"
.text:0000000140013B2A mov rcx, rbx ; hModule
.text:0000000140013B2D call cs:__imp_GetProcAddress
.text:0000000140013B34 nop dword ptr [rax+rax+00h]
.text:0000000140013B39 mov r15, rax
.text:0000000140013B3C test rax, rax
.text:0000000140013B3F jz loc_140013CB9
.text:0000000140013B45 lea rdx, aNgscbcheckhsti ; "NgscbCheckHSTIPrerequisitesVerified"
.text:0000000140013B4C mov rcx, rbx ; hModule
.text:0000000140013B4F call cs:__imp_GetProcAddress
.text:0000000140013B56 nop dword ptr [rax+rax+00h]
.text:0000000140013B5B mov r13, rax
.text:0000000140013B5E test rax, rax
.text:0000000140013B61 jz loc_140013CB9
.text:0000000140013B67 lea rdx, aNgscbcheckdmas ; "NgscbCheckDmaSecurity"
.text:0000000140013B6E mov rcx, rbx ; hModule
.text:0000000140013B71 call cs:__imp_GetProcAddress
There's also a registry key checked SYSTEM\CurrentControlSet\Control\BitLocker\AutoDE\HSTI:
.text:0000000140013C10 lea r8, ?NGSCB_AUTODE_HSTI_REQUIRED##3QBGB ; "HSTIVerificationRequired"
.text:0000000140013C17 mov [rsp+60h+pcbData], rax ; pcbData
.text:0000000140013C1C lea rdx, ?NGSCB_AUTODE_HSTI_PREREQS##3QBGB ; "SYSTEM\\CurrentControlSet\\Control\\Bit"...
.text:0000000140013C23 lea rax, [rbp+var_1C]
.text:0000000140013C27 mov r9d, 10h ; dwFlags
.text:0000000140013C2D mov [rsp+60h+pvData], rax ; pvData
.text:0000000140013C32 mov rcx, 0FFFFFFFF80000002h ; hkey
.text:0000000140013C39 and [rsp+60h+var_40], 0
.text:0000000140013C3F call cs:__imp_RegGetValueW
and some other functions (NgscbCheckPreventDeviceEncryption, NgscbGetWinReConfiguration, FveCheckTpmCapability, ...) , once again, all from the fveapi.dll module.
So basically the checks are all based on functions from this DLL. It seems that none of them are documented (as far as I can see with a quick search).
I didn't find anything around in the DeviceEncryptionDataPoints caller (which is basically the main() function), since the next calls are dealing with checking the hypervisor capabilities.

Related

How to add my custom c++ logic to output some register info in the middle of a fuction?

I had use ida and x64dbg find some logic I care about. The development enviroment is windows x64 , visual studio 2017 .The register value I care out is in the middle of function(000000006137C034).I can not use minihook to hook sub_xxx, then in the detoure fuction I can output some info I have analized.
Disassemble code in a dll I want to analyze
.text:000000006137BFE0 ; __int64 __fastcall sub_6137BFE0(__int64, __int64, __int64, int)
.text:000000006137BFE0 sub_6137BFE0 proc near ; DATA XREF: .rdata:000000006286BB78↓o
.text:000000006137BFE0 ; .pdata:00000000670C06BC↓o
.text:000000006137BFE0
.text:000000006137BFE0 var_28 = dword ptr -28h
.text:000000006137BFE0 var_20 = dword ptr -20h
.text:000000006137BFE0 var_18 = dword ptr -18h
.text:000000006137BFE0 arg_0 = qword ptr 8
.text:000000006137BFE0 arg_8 = qword ptr 10h
.text:000000006137BFE0 arg_10 = qword ptr 18h
.text:000000006137BFE0
.text:000000006137BFE0 mov [rsp+arg_0], rbx
.text:000000006137BFE5 mov [rsp+arg_8], rbp
.text:000000006137BFEA mov [rsp+arg_10], rsi
.text:000000006137BFEF push rdi
.text:000000006137BFF0 sub rsp, 40h
.text:000000006137BFF4 mov rbp, rdx
.text:000000006137BFF7 mov [rsp+48h+var_18], 1
.text:000000006137BFFF mov rdx, [rcx+8]
.text:000000006137C003 mov edi, r9d
.text:000000006137C006 mov rsi, r8
.text:000000006137C009 mov [rsp+48h+var_20], 8
.text:000000006137C011 mov ecx, 0A0h
.text:000000006137C016 mov [rsp+48h+var_28], 4E2h
.text:000000006137C01E mov r9d, 0FF12FD5Ah
.text:000000006137C024 xor r8d, r8d
.text:000000006137C027 call global_new_handler
.text:000000006137C02C mov rbx, rax
.text:000000006137C02F test rax, rax
.text:000000006137C032 jz short loc_6137C05F
.text:000000006137C034 mov rcx, rax
{
#here I want to insert logic to output some memory info pointed by register.
#After doing this , the process continue to excute.
# add code : jump to addr of my own code
}
.text:000000006137C037 call sub_61367440
.text:000000006137C03C mov qword ptr [rbx+98h], 0
.text:000000006137C047 lea rax, off_6286B8A8
.text:000000006137C04E mov [rbx], rax
.text:000000006137C051 mov rax, rbx
.text:000000006137C054 mov [rbx+38h], rbp
.text:000000006137C058 mov [rbx+40h], rsi
.text:000000006137C05C mov [rbx+48h], edi
.text:000000006137C05F
.text:000000006137C05F loc_6137C05F: ; CODE XREF: sub_6137BFE0+52↑j
.text:000000006137C05F mov rbx, [rsp+48h+arg_0]
.text:000000006137C064 mov rbp, [rsp+48h+arg_8]
.text:000000006137C069 mov rsi, [rsp+48h+arg_10]
.text:000000006137C06E add rsp, 40h
.text:000000006137C072 pop rdi
.text:000000006137C073 retn
.text:000000006137C073 sub_6137BFE0 endp
.text:000000006137C073
I found thess papers The-Beginners-Guide-to-Codecaves, Easy-Mid-Hook
, code cave is similar to what I want . I can add my custom logic ,but it's 32 bit project. I should modify some code in 000000006137C034, jump to My own code , after some work , the process continue to excute.
My Own Code Write By C++ On another project which load the dll.
# save all registers, which maybe written by asm
# monitor logic , which written by c++
# restore all registers
# return to 000000006137C037 , so the process continue to excute
There may be some technical point:
a. Modify code segment to add jump instruction during process running ,so the process can jump to my own code;
b. How to realize my own code : stack and register save and restore, and how to deal with the return addr.
c. Other things needs paying attention to for my poor knowledge of x64 instruction and reversing engineering.
I hope some one can give me some hint( paper , open source library, or web page) so I can keep forward to learning, and finally realize these functionity I needed.
Thanks!
I have found some page help me to understand, and I will keep updating what I found during realizing my expected functionity.
1.Hooking-By-Example
2.Adding x86, x64 Assembly Language code to the Visual Studio C++ project.
3.What is the 'shadow space' in x64 assembly?

C++ inline asm move WCHAR in 32-bit register

I am trying to practice the inline ASM in C++ :) Maybe outdated, but it is interesting, to know how CPU is executing the code.
So, what I am trying to do here, is to loop through processes and get a handle of needed one :) I am using for that already created methods from tlhelp32
I have this code:
HANDLE RetHandle = nullptr, snap;
int SizeOfPE = sizeof(PROCESSENTRY32), pid; PROCESSENTRY32 pe;
int PA = PROCESS_ALL_ACCESS;
const char* Pname = "explorer.exe";
__asm
{
mov eax, pe
mov ebx, this
mov ecx, [ebx]pe.dwSize
mov ecx, SizeOfPE
mov[ebx]pe.dwSize, ecx
mov eax, PA
mov ebx,0
call CreateToolhelp32Snapshot
mov eax,snap
label1:
mov eax, snap
mov ebx, [pe]
call Process32First
cmp eax,1
jne exitLabel
Process32NextLoop:
mov eax, snap
mov ebx, [pe]
call Process32Next
cmp eax, 1
jne Process32NextLoop
mov edx, pe
mov ecx, [edx].szExeFile
cmp ecx, Pname
je ExitLoop
jne Process32NextLoop
ExitLoop:
mov eax, [ebx].th32ProcessID
mov pid, eax
ExitLabel:
ret
}
Apparently, it is throwing error in th32ProcessID as well, however, it is just regular int.
Have been searching, but haven't found the equivalent for movl in C++

What module instance should be passed to CreateCursor method?

CreateCursor function takes HINSTANCE as a first argument as described here:
https://msdn.microsoft.com/en-us/library/windows/desktop/ms648385(v=vs.85).aspx
It can be NULL but why is it required on the first place? My guess is that it can be used to find app main window and determine display driver to be used for cursor creation. But maybe someone have a better explanation?
On my Windows Server 2008 R2 system the handle is not used at all. Here is the disassembly with a few added comments:
0:000> u createcursor
USER32!CreateCursor:
00000000`77a40cb4 488bc4 mov rax,rsp
00000000`77a40cb7 48895808 mov qword ptr [rax+8],rbx
00000000`77a40cbb 48896810 mov qword ptr [rax+10h],rbp
00000000`77a40cbf 48897018 mov qword ptr [rax+18h],rsi
00000000`77a40cc3 48897820 mov qword ptr [rax+20h],rdi
00000000`77a40cc7 4154 push r12
00000000`77a40cc9 4881ecc0000000 sub rsp,0C0h
00000000`77a40cd0 33db xor ebx,ebx
0:000> u
USER32!CreateCursor+0x1e:
00000000`77a40cd2 458be1 mov r12d,r9d
00000000`77a40cd5 418bf8 mov edi,r8d
00000000`77a40cd8 3bd3 cmp edx,ebx
00000000`77a40cda 8bf2 mov esi,edx
; If xHotSpot is negative, return error
00000000`77a40cdc 0f8c60070100 jl USER32!CreateCursor+0xb0 (00000000`77a51442)
00000000`77a40ce2 413bd1 cmp edx,r9d
; If xHotSpot is greater than nWidth return error
00000000`77a40ce5 0f8f57070100 jg USER32!CreateCursor+0xb0 (00000000`77a51442)
00000000`77a40ceb 443bc3 cmp r8d,ebx
0:000> u
USER32!CreateCursor+0x36:
; If yHotSpot is negative, return error
00000000`77a40cee 0f8c4e070100 jl USER32!CreateCursor+0xb0 (00000000`77a51442)
00000000`77a40cf4 8bac24f0000000 mov ebp,dword ptr [rsp+0F0h]
00000000`77a40cfb 443bc5 cmp r8d,ebp
; If yHotSpot is greater than nHeight return error
00000000`77a40cfe 0f8f3e070100 jg USER32!CreateCursor+0xb0 (00000000`77a51442)
; This LEA overwrites whatever was passed in as the application handle!!!
; RCX was not saved before this point, so handle is lost
00000000`77a40d04 488d4c2430 lea rcx,[rsp+30h]
00000000`77a40d09 33d2 xor edx,edx
00000000`77a40d0b 41b888000000 mov r8d,88h
00000000`77a40d11 e8828affff call USER32!memset (00000000`77a39798)

Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call

#include<stdio.h>
int a[100];
int main(){
char UserName[100];
char *n=UserName;
char *q=NULL;
char Serial[200];
q=Serial;
scanf("%s",UserName);
//this is about
__asm{
pushad
mov eax,q
push eax
mov eax,n
push eax
mov EAX,EAX
mov EAX,EAX
CALL G1
LEA EDX,DWORD PTR SS:[ESP+10H]
jmp End
G1:
SUB ESP,400H
XOR ECX,ECX
PUSH EBX
PUSH EBP
MOV EBP,DWORD PTR SS:[ESP+40CH]
PUSH ESI
PUSH EDI
MOV DL,BYTE PTR SS:[EBP]
TEST DL,DL
JE L048
LEA EDI,DWORD PTR SS:[ESP+10H]
MOV AL,DL
MOV ESI,EBP
SUB EDI,EBP
L014:
MOV BL,AL
ADD BL,CL
XOR BL,AL
SHL AL,1
OR BL,AL
MOV AL,BYTE PTR DS:[ESI+1]
MOV BYTE PTR DS:[EDI+ESI],BL
INC ECX
INC ESI
TEST AL,AL
JNZ L014
TEST DL,DL
JE L048
MOV EDI,DWORD PTR SS:[ESP+418H]
LEA EBX,DWORD PTR SS:[ESP+10H]
MOV ESI,EBP
SUB EBX,EBP
L031:
MOV AL,BYTE PTR DS:[ESI+EBX]
PUSH EDI
PUSH EAX
CALL G2
MOV AL,BYTE PTR DS:[ESI+1]
ADD ESP,8
ADD EDI,2
INC ESI
TEST AL,AL
JNZ L031
MOV BYTE PTR DS:[EDI],0
POP EDI
POP ESI
POP EBP
POP EBX
ADD ESP,400H
RETN
L048:
MOV ECX,DWORD PTR SS:[ESP+418H]
POP EDI
POP ESI
POP EBP
MOV BYTE PTR DS:[ECX],0
POP EBX
ADD ESP,400H
RETN
G2:
MOVSX ECX,BYTE PTR SS:[ESP+4]
MOV EAX,ECX
AND ECX,0FH
SAR EAX,4
AND EAX,0FH
CMP EAX,0AH
JGE L009
ADD AL,30H
JMP L010
L009:
ADD AL,42H
L010:
MOV EDX,DWORD PTR SS:[ESP+8]
CMP ECX,0AH
MOV BYTE PTR DS:[EDX],AL
JGE L017
ADD CL,61H
MOV BYTE PTR DS:[EDX+1],CL
RETN
L017:
ADD CL,45H
MOV BYTE PTR DS:[EDX+1],CL
RETN
End:
mov eax,eax
popad
}
printf("%s\n",Serial);
return 0;
}
Can you help me?
this problem about Asm,I don't know why cause this result.
this program is very easy,and it about a program of internal code.
Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call. This is usually a result of calling a function declared with one calling convention with a function pointer declared with a different calling convention.
It seems the two parameters which are pushed onto the stack before the call to G1 are never popped from the stack.
Possibly it happens because at the beginning of the function G1 you SUB ESP,400H, after L031 you make ADD ESP,8 and at the end you ADD ESP,400H. It seems like ESP before the G1 call is by 8 less then after call.
EDIT: Regarding to the coding style of assembly function please see this. Here briefly described what are the caller's responsibilities and what are callee's responsibilities, that are regarded to ESP.

Call not returning properly [X86_ASM]

This is C++ using x86 inline assembly [Intel syntax]
Function:
DWORD *Call ( size_t lArgs, ... ){
DWORD *_ret = new DWORD[lArgs];
__asm {
xor edx, edx
xor esi, esi
xor edi, edi
inc edx
start:
cmp edx, lArgs
je end
push eax
push edx
push esi
mov esi, 0x04
imul esi, edx
mov ecx, esi
add ecx, _ret
push ecx
call dword ptr[ebp+esi] //Doesn't return to the next instruction, returns to the caller of the parent function.
pop ecx
mov [ecx], eax
pop eax
pop edx
pop esi
inc edx
jmp start
end:
mov eax, _ret
ret
}
}
The purpose of this function is to call multiple functions/addresses without calling them individually.
Why I'm having you debug it?
I have to start school for the day, and I need to have it done by evening.
Thanks alot, iDomo
Thank you for a complete compile-able example, it makes solving problems much easier.
According to your Call function signature, when the stack frame is set up, the lArgs is at ebp+8 , and the pointers start at ebp+C. And you have a few other issues. Here's a corrected version with some push/pop optimizations and cleanup, tested on MSVC 2010 (16.00.40219.01) :
DWORD *Call ( size_t lArgs, ... ) {
DWORD *_ret = new DWORD[lArgs];
__asm {
xor edx, edx
xor esi, esi
xor edi, edi
inc edx
push esi
start:
cmp edx, lArgs
; since you started counting at 1 instead of 0
; you need to stop *after* reaching lArgs
ja end
push edx
; you're trying to call [ebp+0xC+edx*4-4]
; a simpler way of expressing that - 4*edx + 8
; (4*edx is the same as edx << 2)
mov esi, edx
shl esi, 2
add esi, 0x8
call dword ptr[ebp+esi]
; and here you want to write the return value
; (which, btw, your printfs don't produce, so you'll get garbage)
; into _ret[edx*4-4] , which equals ret[esi - 0xC]
add esi, _ret
sub esi, 0xC
mov [esi], eax
pop edx
inc edx
jmp start
end:
pop esi
mov eax, _ret
; ret ; let the compiler clean up, because it created a stack frame and allocated space for the _ret pointer
}
}
And don't forget to delete[] the memory returned from this function after you're done.
I notice that, before calling, you push EAX, EDX, ESI, ECX (in order), but don't pop in the reverse order after returning. If the first CALL returns properly, but subsequent ones don't, that could be the issue.