Porting Assembly to C/C++? - c++

I would like to have this x86 ASM code ported to C or C++, as I don't understand ASM =)
Searching Google it seams Relogix and IDA Pro can do it. But I don't suppose they are cheap, given I only have this one source.
Understanding the math or the algorithm how it works would be just as good, as I am going to use OpenGL anyway.
Are there other methods?
;
; a n d r o m e d a
;
; a 256b demo
; by insomniac/neon
;
code SEGMENT
ASSUME CS:code, DS:code
p386
LOCALS
ORG 100h
max = 4096
maxZ = 5000
b EQU byte ptr
Start: lea di,vars
mov ch,60
rep stosw
mov al,13h
int 10h
p al: mov al,cl
mov dx,3c8h
out dx,al
inc dx
cmp al,64
jb b64_1
mov al,63
b64_1: out dx,al
mov al,cl
shr al,1
out dx,al
out dx,al
loop pal
.main: push 8000h
pop ES
mov si,max
.loop: mov ax,Z[si]
cmp ax,maxZ-(maxZ/4)
jg NewStar
cmp ax,2
jg Zok
NewStar:
mov ax,bp
mov X[si],ax
imul ax,8405h
inc ax
mov bp,ax
shr ax,6
sub ax,400
mov Y[si],ax
mov Z[si],maxZ-(maxZ/2)
Zok: mov ax,X[si]
movsx dx,ah
shl ax,8
mov cx,Z[si]
idiv cx
add ax,320/2
cmp ax,320-1
jge NewStar
cmp ax,1
jle NewStar
mov di,ax
mov ax,Y[si]
movsx dx,ah
shl ax,8
idiv cx
add ax,200/2
imul ax,320
add di,ax
mov al,127
stosb
mov ax,X[si]
cmp ax,00
jge .add
neg ax
shr ax,6
add Y[si],ax
jmp .notadd
.add: shr ax,6
sub Y[si],ax
.notadd:
add Z[si],ax
mov ax,Y[si]
sar ax,3
add X[si],ax
.NextStar:
dec si
dec si
jnz .loop
push DS
push ES
pop DS
xor di,di
xor cx,cx
.blur: movzx ax,DS:[di]
movzx dx,DS:[di+1]
add ax,dx
mov dl,DS:[di-320]
add ax,dx
mov dl,DS:[di+321]
add ax,dx
shr ax,2
cmp al,0
je .skip
dec ax
.skip: stosb
loop .blur
push 0a000h
pop ES
mov si,di
mov ch,81h
rep movsw
pop DS
mov dx,3dah
.vrt: in al,dx
test al,8
jz .vrt
in al,60h
dec ax
jnz .main
endprog:
mov al,3
int 10h
ret
LABEL vars
X dw max DUP (?)
Y dw max DUP (?)
Z dw max DUP (?)
code ENDS
END Start

In general case, this cannot be done. In this particular case, this cannot be done because this assembly program interacts with PC BIOS directly, using int 10h to turn on 320x200 256 VGA mode, and it interacts with PC hardware directly, by writing to IO ports 0x3c8 and 0x3c9 (this sets the VGA palette) and by reading from 0x3da (VGA status register) and 0x60 (PC keyboard microcontroller). It also writes directly to VGA video memory.
Under the conditions of executing on a PC-compatible computer with MS-DOS or similar OS (or, within a simulated environment such as dosbox), this can be done: you can either make each CPU register a C variable and each assembly mnemonic a C function that modifies those variables or writes at absolute memory addresses or IO ports (with outb() and inb()), or, and I think this would be a much more interesting task, understand the math this demo does, and implement that in a portable manner.
Either way, I haven't heard of tools that could do this automatically. Existing tools might handle simple logic, but understanding a demo is never an easy task! What automatic program can tell that
imul ax,8405h
inc ax
should be replaced with ax = rand();?

You could throw it on RentaCoder and pay someone a few $ to write a C version by hand, including an annotation how it was done.

There are quite a few methods of doing so, for example this or this. ;-)

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?

Get device encryption support information

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.

Conditional jumps in assembler always give same result [duplicate]

Basic question here,
I wrote the following block:
IDEAL
MODEL small
STACK 100h
DATASEG
Var1 db 4
Var2 db 2
CODESEG
start:
mov ax, #data
mov ds, ax
xor ax, ax
mov al, [Var1]
cmp al, [Var2]
jg Var1Greater
mov ax, 1
Var1Greater:
mov ax, 0
I'm new to assembly.
I wanted to create a code that compares [Var1] to [Var2].
IF(!) [Var1] is greater than [Var2], execute mov ax, 1. IF(1) anything else(equal or less) excecute, mov ax, 0.
How can this be done? the code I wrote executes both instructions if the condition is true.
Ah, Turbo Assembler "Ideal" mode; It has been a while since I last saw it. I love Ideal mode. It is so much better thought-out and it makes so much more sense than Microsoft Assembler's syntax.
Well, what is happening is that both instructions get executed.
First, mov ax, 0 gets executed, and then control falls through to the next statement, which is mov ax, 1, so what you are left with in ax is 1.
Labels in assembly language do not magically cause control to jump elsewhere. They do not cause the assembler to emit any instructions. They only exist so that you can indicate the target of another jump instruction.
So, what you need is:
...
cmp al, [Var2]
jg Var1Greater
mov ax, 0
jmp skip
Var1Greater:
mov ax, 1
skip:
also, it is good form when writing assembly language to use xor ax, ax instead of mov ax, 0.
You must jump over Var1Greater too to skip mov ax, 1 instruction. As alternative you may do it like:
mov ax, [Var1]
cmp ax, [Var2]
mov ax, 1
jg skip0
mov ax, 0
skip0:

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)

Code executes condition wrong?

Basic question here,
I wrote the following block:
IDEAL
MODEL small
STACK 100h
DATASEG
Var1 db 4
Var2 db 2
CODESEG
start:
mov ax, #data
mov ds, ax
xor ax, ax
mov al, [Var1]
cmp al, [Var2]
jg Var1Greater
mov ax, 1
Var1Greater:
mov ax, 0
I'm new to assembly.
I wanted to create a code that compares [Var1] to [Var2].
IF(!) [Var1] is greater than [Var2], execute mov ax, 1. IF(1) anything else(equal or less) excecute, mov ax, 0.
How can this be done? the code I wrote executes both instructions if the condition is true.
Ah, Turbo Assembler "Ideal" mode; It has been a while since I last saw it. I love Ideal mode. It is so much better thought-out and it makes so much more sense than Microsoft Assembler's syntax.
Well, what is happening is that both instructions get executed.
First, mov ax, 0 gets executed, and then control falls through to the next statement, which is mov ax, 1, so what you are left with in ax is 1.
Labels in assembly language do not magically cause control to jump elsewhere. They do not cause the assembler to emit any instructions. They only exist so that you can indicate the target of another jump instruction.
So, what you need is:
...
cmp al, [Var2]
jg Var1Greater
mov ax, 0
jmp skip
Var1Greater:
mov ax, 1
skip:
also, it is good form when writing assembly language to use xor ax, ax instead of mov ax, 0.
You must jump over Var1Greater too to skip mov ax, 1 instruction. As alternative you may do it like:
mov ax, [Var1]
cmp ax, [Var2]
mov ax, 1
jg skip0
mov ax, 0
skip0: