why can't visual studio 2015 resolve dqword when compiling .asm? - visual-studio

I wanted to compile my strlen_sse.asm to accomplish a function strlen_sse,which has the same function as strlen but more quick. And my code is below:
.CODE
EQUAL_EACH = 00001000b
strlen_sse PROC
;ecx = string
mov eax, -16
mov edx, ecx
pxor xmm0, xmm0
STRLEN_LOOP:
add eax, 16
PcmpIstrI xmm0, dqword[edx+eax], EQUAL_EACH
jnz STRLEN_LOOP
add eax, ecx
ret
strlen_sse ENDP
END
I have set the command line and other properties like the picture below:
In the picture 命令行 is what the command line is in Chinese. and 输出 is the same as Output
When I built the project I got messages below:
1> Performing Custom Build Tools
1> Microsoft (R) Macro Assembler (x64) Version 14.00.23026.0
1> Copyright (C) Microsoft Corporation. All rights reserved.
1>
1> Assembling: strlen_sse.asm
1>strlen_sse.asm(13): error A2006: undefined symbol : dqword
How to solve it?

I'm not sure what do you mean by dqword. I guess you are trying to use assembly code intended for some other assembler. I should use XMMWORD PTR prefix for a memory operand of 128-bit size in masm.
Here is the modified code which compiles with ml.exe and ml64.exe:
tmp SEGMENT
strlen_sse PROC
;ecx = string
mov eax, -16
mov edx, ecx
pxor xmm0, xmm0
STRLEN_LOOP:
add eax, 16
PcmpIstrI xmm0, xmmword ptr [edx+eax], 00001000b
jnz STRLEN_LOOP
add eax, ecx
ret
strlen_sse ENDP
tmp ENDS
END
Beware: I have no idea whether it works properly or not.

Related

FASM write Hello World to console with NO includes or dependencies at all

I've seen
How to write hello world in assembler under Windows?
and
Writing hello,world to console in Fasm with DOS
How to write to the console in fasm?
I've tried / seen code like this MASM example from this answer
;---ASM Hello World Win64 MessageBox
extrn MessageBoxA: PROC
extrn ExitProcess: PROC
.data
title db 'Win64', 0
msg db 'Hello World!', 0
.code
main proc
sub rsp, 28h
mov rcx, 0 ; hWnd = HWND_DESKTOP
lea rdx, msg ; LPCSTR lpText
lea r8, title ; LPCSTR lpCaption
mov r9d, 0 ; uType = MB_OK
call MessageBoxA
add rsp, 28h
mov ecx, eax ; uExitCode = MessageBox(...)
call ExitProcess
main endp
End
(to which I get an error "Illegal instruction" on windows 64 bit extrn MessageBoxA:PROC because FASM doesn't understand that MASM directive.)
also this FASM example from this question
; Example of 64-bit PE program
format PE64 GUI
entry start
section '.text' code readable executable
start:
sub rsp,8*5 ; reserve stack for API use and make stack dqword aligned
mov r9d,0
lea r8,[_caption]
lea rdx,[_message]
mov rcx,0
call [MessageBoxA]
mov ecx,eax
call [ExitProcess]
section '.data' data readable writeable
_caption db 'Win64 assembly program',0
_message db 'Hello World!',0
section '.idata' import data readable writeable
dd 0,0,0,RVA kernel_name,RVA kernel_table
dd 0,0,0,RVA user_name,RVA user_table
dd 0,0,0,0,0
kernel_table:
ExitProcess dq RVA _ExitProcess
dq 0
user_table:
MessageBoxA dq RVA _MessageBoxA
dq 0
kernel_name db 'KERNEL32.DLL',0
user_name db 'USER32.DLL',0
_ExitProcess dw 0
db 'ExitProcess',0
_MessageBoxA dw 0
db 'MessageBoxA',0
but it displays a message box and also has external dependencies "kernel32.dll" and "user32.dll"
also tried this example from the FASM forum
format pe console
include 'win32ax.inc'
entry main
section '.data!!!' data readable writeable
strHello db 'Hello World !',13,10,0
strPause db 'pause',0
section '.txt' code executable readable
main:
; you can use crt functions or windows API.
cinvoke printf,strHello
cinvoke system,strPause; or import getc()
; or
; invoke printf,srtHello
; add esp, 4
; or use WriteFile and GetStdHandle APIs
push 0
call [ExitProcess]
section '.blah' import data readable
library kernel32,'kernel32.dll',\
msvcrt,'msvcrt.dll' ;; C-Run time from MS. This is always on every windows machine
import kernel32,\
ExitProcess,'ExitProcess'
import msvcrt,\
printf,'printf',\
system,'system'
but it depends on win32ax.inc and other imports
also
format PE console
include 'win32ax.inc'
.code
start:
invoke WriteConsole,<invoke GetStdHandle,STD_OUTPUT_HANDLE>,"Hello World !",13,0
invoke Sleep,-1
.end start
but requires "win32ax.inc" import
closest I could find without the win32ax from the FASM forum:
format pe64 console
entry start
STD_OUTPUT_HANDLE = -11
section '.text' code readable executable
start:
sub rsp,8*7 ; reserve stack for API use and make stack dqword aligned
mov rcx,STD_OUTPUT_HANDLE
call [GetStdHandle]
mov rcx,rax
lea rdx,[message]
mov r8d,message_length
lea r9,[rsp+4*8]
mov qword[rsp+4*8],0
call [WriteFile]
mov ecx,eax
call [ExitProcess]
section '.data' data readable writeable
message db 'Hello World!',0
message_length = $ - message
section '.idata' import data readable writeable
dd 0,0,0,RVA kernel_name,RVA kernel_table
dd 0,0,0,0,0
kernel_table:
ExitProcess dq RVA _ExitProcess
GetStdHandle dq RVA _GetStdHandle
WriteFile dq RVA _WriteFile
dq 0
kernel_name db 'KERNEL32.DLL',0
user_name db 'USER32.DLL',0
_ExitProcess db 0,0,'ExitProcess',0
_GetStdHandle db 0,0,'GetStdHandle',0
_WriteFile db 0,0,'WriteFile',0
but still requires the kernel32.dll and user32.dll
Any way to do this without any external DLLs at all? I know just the program fasm itself does it, and prints to the console, doesn't it?
Any way to do this without any external DLLs at all?
Under Windows: Definitely no!
Windows uses some methods (probably syscall) to enter the operating system, however, there are no official entry points.
This means that it is (unlikely but) possible that exactly the same program that shows the "Hello world" message box in the current Windows version will do something completely different after the next Windows update!
Because Microsoft is assuming that every Windows program is only calling the OS by using the .dll files that match the kernel version, they can do this.
I don't know about Windows 10, but an older Windows version (I don't remember if it was XP, Vista or 7) even simply assumed that an .exe file returns at once if it does not use any .dll file: The program was not even started in this case!
I know just the program fasm itself does it, and prints to the console
That is not the case, fasm is also using the kernel32 APIs.
FWIW kernel32 is loaded into the memory space of every process in Windows, so there is no penalty or overhead in using the kernel32 APIs.
You may like this Windows example in €ASM, which doesn't explicitly mention any DLL and doesn't require other external libraries.
Just save the source as "bluej.asm", assemble and link with euroasm bluej.asm and run as bluej.exe.
Nevertheless, you won't get away without using API functions imported from the default Windows system library "kernel32.dll".
bluej PROGRAM Format=PE, Entry=Start:
IMPORT GetStdHandle,WriteFile,ExitProcess
Start: PUSH -11 ; Param 1: standard output handle identificator.
CALL GetStdHandle; Return StdOutput handle in EAX.
PUSH 0 ; Param 5: no overlap.
PUSH Written ; Param 4: Address of a variable to store number of written bytes.
PUSH MsgSize ; Param 3: Number of bytes to write.
PUSH Msg ; Param 2: Address of text.
PUSH EAX ; Param 1: Output file handle.
CALL WriteFile ; System call.
PUSH 0 ; Errorlevel.
CALL ExitProcess ; System call.
Written DD 0
Msg DB "Hello, world!"
MsgSize EQU $ - Msg
ENDPROGRAM
What constitures as "dependency" to you? If you want to avoid even operating system DLL's, then you're probably out of luck. You can't rely on syscall numbers alone.
"no dependencies" can also mean "just using existing OS DLL's", such as ntdll, kernel32, etc., but without using 3rd party DLL's that may not be present, such as a specific version of the C runtime.
One method I would like to show is retrieving function pointers from the PEB. This is code that I've written and that I personally use, if I want to have shellcode that has no import section.
PebGetProcAddress works similarly to GetProcAddress, except that the DLL name and function name must be a hash, and the DLL must be loaded by using LoadLibrary.
This may not answer your question exactly, but I hope it gets you somewhat closer to your goal or help others who read it.
PebApi.asm
proc PebGetProcAddress ModuleHash:DWORD, FunctionHash:DWORD
local FirstEntry:DWORD
local CurrentEntry:DWORD
local ModuleBase:DWORD
local ExportDirectory:DWORD
local NameDirectory:DWORD
local NameOrdinalDirectory:DWORD
local FunctionCounter:DWORD
; Get InMemoryOrderModuleList from PEB
mov eax, 3
shl eax, 4
mov eax, [fs:eax] ; fs:0x30
mov eax, [eax + PEB.Ldr]
mov eax, [eax + PEB_LDR_DATA.InMemoryOrderModuleList.Flink]
mov [FirstEntry], eax
mov [CurrentEntry], eax
; Find module by hash
.L_module:
; Compute hash of case insensitive module name
xor edx, edx
mov eax, [CurrentEntry]
movzx ecx, word[eax + LDR_DATA_TABLE_ENTRY.BaseDllName.Length]
test ecx, ecx
jz .C_module
mov esi, [eax + LDR_DATA_TABLE_ENTRY.BaseDllName.Buffer]
xor eax, eax
cld
.L_module_hash:
lodsb
ror edx, 13
add edx, eax
cmp al, 'a'
jl #f
sub edx, 0x20 ; Convert lower case letters to upper case
##: dec ecx
test ecx, ecx
jnz .L_module_hash
; Check, if module is found by hash
cmp edx, [ModuleHash]
jne .C_module
; Get module base
mov eax, [CurrentEntry]
mov eax, [eax + LDR_DATA_TABLE_ENTRY.DllBase]
mov [ModuleBase], eax
; Get export directory
mov eax, [ModuleBase]
add eax, [eax + IMAGE_DOS_HEADER.e_lfanew]
mov eax, [eax + IMAGE_NT_HEADERS32.OptionalHeader.DataDirectoryExport.VirtualAddress]
add eax, [ModuleBase]
mov [ExportDirectory], eax
; Get name table
mov eax, [ExportDirectory]
mov eax, [eax + IMAGE_EXPORT_DIRECTORY.AddressOfNames]
add eax, [ModuleBase]
mov [NameDirectory], eax
; Get name ordinal table
mov eax, [ExportDirectory]
mov eax, [eax + IMAGE_EXPORT_DIRECTORY.AddressOfNameOrdinals]
add eax, [ModuleBase]
mov [NameOrdinalDirectory], eax
; Find function in export directory by hash
mov [FunctionCounter], 0
.L_functions:
mov eax, [ExportDirectory]
mov eax, [eax + IMAGE_EXPORT_DIRECTORY.NumberOfNames]
cmp eax, [FunctionCounter]
je .E_functions
; Compute hash of function name
xor edx, edx
mov esi, [NameDirectory]
mov esi, [esi]
add esi, [ModuleBase]
xor eax, eax
cld
.L_function_hash:
lodsb
test al, al
jz .E_function_hash
ror edx, 13
add edx, eax
jmp .L_function_hash
.E_function_hash:
; Check, if function is found by hash
cmp edx, [FunctionHash]
jne .C_functions
; Return function address
mov eax, [ExportDirectory]
mov eax, [eax + IMAGE_EXPORT_DIRECTORY.AddressOfFunctions]
add eax, [ModuleBase]
mov ebx, [NameOrdinalDirectory]
movzx ebx, word[ebx]
lea eax, [eax + ebx * 4]
mov eax, [eax]
add eax, [ModuleBase]
ret
.C_functions:
add [NameDirectory], 4
add [NameOrdinalDirectory], 2
inc [FunctionCounter]
jmp .L_functions
.E_functions:
; Function not found in module's export table
xor eax, eax
ret
.C_module:
; Move to next module, exit loop if CurrentEntry == FirstEntry
mov eax, [CurrentEntry]
mov eax, [eax + LIST_ENTRY.Flink]
mov [CurrentEntry], eax
cmp eax, [FirstEntry]
jne .L_module
; Module not found
xor eax, eax
ret
endp
PebApi.inc
macro pebcall modulehash, functionhash, [arg]
{
common
if ~ arg eq
reverse
pushd arg
common
end if
stdcall PebGetProcAddress, modulehash, functionhash
call eax
}
Example
PEB_User32Dll = 0x63c84283
PEB_MessageBoxW = 0xbc4da2be
; pebcall translates to a call to PebGetProcAddress and the call to the returned function pointer
pebcall PEB_User32Dll, PEB_MessageBoxW, NULL, 'Hello, World!', NULL, MB_OK
How to generate hashes for module names and function names
#define ROTR(value, bits) ((DWORD)(value) >> (bits) | (DWORD)(value) << (32 - (bits)))
DWORD ComputeFunctionHash(LPCSTR str)
{
DWORD hash = 0;
while (*str)
{
hash = ROTR(hash, 13) + *str++;
}
return hash;
}
DWORD ComputeModuleNameHash(LPCSTR str, USHORT length)
{
DWORD hash = 0;
for (USHORT i = 0; i < length; i++)
{
hash = ROTR(hash, 13) + (str[i] >= 'a' ? str[i] - 0x20 : str[i]);
}
return hash;
}

Seemingly wrong instruction pointer reported by VS2017

Edit:
I've investigated more, and the problem reported below seems to happen only when I use Visual Studio 2017 to pause the process. It also seems that when rip is pointing to an invalid location, it's always a +1 byte offset from the correct instruction start.
Also, for context, this is a large C++ project with lots of dlls, some compiled with MSVC 2015, the rest with icc (intel compiler 2017). This is run in a python process using boost C++/python bindings.
Original post:
I am pausing my program randomly to see what are my threads doing during some heavy computation.
Note that I am not debugging a crash, resuming the program works fine.
Howver the VS debugger is sometimes unable to dissassemble the machine code.
For instance, on one thread where rip=000007FE8B048EE2, it shows this:
000007FE8B048EDE ?? ??
000007FE8B048EDF ?? ??
000007FE8B048EE0 ?? ??
000007FE8B048EE1 ?? ??
}
if (params.derandomize) {
000007FE8B048EE2 adc ebp,eax
GetRNG().Seed(id);
000007FE8B048EE4 pop rax
000007FE8B048EE5 wait
000007FE8B048EE6 adc byte ptr [rax],al
000007FE8B048EE8 mov rcx,rax
The decoded x86 instructions also seem wrong (adc, pop, wait, adc ??), so I tried to attach WinDBG as well (non invasive mode):
0:019> u rip
somedll!<lambda239>::operator()+0x132:
000007fe`8b048ee2 13e8 adc ebp,eax
000007fe`8b048ee4 58 pop rax
000007fe`8b048ee5 9b wait
000007fe`8b048ee6 1000 adc byte ptr [rax],al
000007fe`8b048ee8 4889c1 mov rcx,rax
000007fe`8b048eeb 8b9570080000 mov edx,dword ptr [rbp+870h]
000007fe`8b048ef1 e8fa911000 call somedll!bla::bla::blabla::blabla::Seed (000007fe`8b1520f0)
000007fe`8b048ef6 4c8ba5b0080000 mov r12,qword ptr [rbp+8B0h]
Ok, it's the same garbage...
But then I tried to dissassemble from an address slightly above rip:
0:019> u rip-30
somedll!<lambda239>::operator()+0x102:
000007fe`8b048eb2 00488b add byte ptr [rax-75h],cl
000007fe`8b048eb5 084863 or byte ptr [rax+63h],cl
000007fe`8b048eb8 81d003000048 adc eax,48000003h
000007fe`8b048ebe 83f8ff cmp eax,0FFFFFFFFh
000007fe`8b048ec1 740a je somedll!<lambda239>::operator()+0x11d (000007fe`8b048ecd)
000007fe`8b048ec3 4889c2 mov rdx,rax
000007fe`8b048ec6 48899570080000 mov qword ptr [rbp+870h],rdx
000007fe`8b048ecd 486381e0030000 movsxd rax,dword ptr [rcx+3E0h]
0:019> u
somedll!<lambda239>::operator()+0x124:
000007fe`8b048ed4 483bd0 cmp rdx,rax
000007fe`8b048ed7 7501 jne somedll!<lambda239>::operator()+0x12a (000007fe`8b048eda)
000007fe`8b048ed9 cc int 3
000007fe`8b048eda 80b96303000000 cmp byte ptr [rcx+363h],0
000007fe`8b048ee1 7413 je somedll!<lambda239>::operator()+0x146 (000007fe`8b048ef6)
000007fe`8b048ee3 e8589b1000 call somedll!bla::bla::blabla::GetRNG (000007fe`8b152a40)
000007fe`8b048ee8 4889c1 mov rcx,rax
000007fe`8b048eeb 8b9570080000 mov edx,dword ptr [rbp+870h]
0:019> u
somedll!<lambda239>::operator()+0x141:
000007fe`8b048ef1 e8fa911000 call somedll!bla::bla::blabla::blabla::Seed (000007fe`8b1520f0)
000007fe`8b048ef6 4c8ba5b0080000 mov r12,qword ptr [rbp+8B0h]
000007fe`8b048efd 488d95f0070000 lea rdx,[rbp+7F0h]
000007fe`8b048f04 488d8dc0070000 lea rcx,[rbp+7C0h]
000007fe`8b048f0b 498b0424 mov rax,qword ptr [r12]
000007fe`8b048f0f 4c8da570080000 lea r12,[rbp+870h]
000007fe`8b048f16 488942d0 mov qword ptr [rdx-30h],rax
000007fe`8b048f1a 4c8962d8 mov qword ptr [rdx-28h],r12
the first instructions "add byte ptr" and "or byte ptr" at 000007fe`8b048eb2 don't make sense because rip-30 likely falls in the middle of an instruction, but after it seems to resync because it corresponds to the source code:
if (id == params.dbgbreak_id) {
__debugbreak();
}
if (params.derandomize) {
GetRNG().Seed(id);
}
000007fe`8b048ecd 486381e0030000 movsxd rax,dword ptr [rcx+3E0h]
000007fe`8b048ed4 483bd0 cmp rdx,rax // if (id == params.dbgbreak_id) {
000007fe`8b048ed7 7501 jne somedll!<lambda239>::operator()+0x12a (000007fe`8b048eda)
000007fe`8b048ed9 cc int 3 // __debugbreak(); }
000007fe`8b048eda 80b96303000000 cmp byte ptr [rcx+363h],0 // if (params.derandomize)
000007fe`8b048ee1 7413 je somedll!<lambda239>::operator()+0x146 (000007fe`8b048ef6)
000007fe`8b048ee3 e8589b1000 call somedll!bla::bla::blabla::GetRNG (000007fe`8b152a40)
000007fe`8b048ee8 4889c1 mov rcx,rax
000007fe`8b048eeb 8b9570080000 mov edx,dword ptr [rbp+870h]
000007fe`8b048ef1 e8fa911000 call somedll!bla::bla::blabla::blabla::Seed (000007fe`8b1520f0)
clearly there is no instruction begining at 000007fe8b048ee2 !
There is je at 000007fe8b048ee1, and call at 000007fe8b048ee3
So... I thought, hmmm there's a bug in the debugger... let's check the registers:
0:019> r
rax=ffffffffffffffff rbx=000000000021d420 rcx=000000000021d5d0
rdx=0000000002696568 rsi=0000000000005d38 rdi=0000000056eefc40
rip=000007fe8b048ee2 rsp=0000000056eef5b0 rbp=0000000056eef5e0
r8=0000000000000006 r9=000000000021d0b8 r10=0000000006456570
r11=0000000000000006 r12=0000000056eefe50 r13=00000000069a8820
r14=000000000021d1a8 r15=0000000056eefe60
iopl=0 nv up ei pl zr na po nc
cs=0033 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000246
What?? rip=000007fe8b048ee2 ?? How is that possible?
It explains why the debugger is showing garbage: it is trying to dissassemble starting from rip, but rip points to the middle of an instruction.
But why is the reported rip wrong? Is the OS culprit?
Am I missing something?

Assembly in visual studio Print the value in registry

I have created a program in visual studio to move values in the registry but i have no way of knowing whether the program actually worked since i cannot see the registr in visual studio 2017
I am running on visual studio 2017. I have a C++ Project that looks like this
extern "C" void doit();
void main()
{
doit();
}
and thsi is what my assembly file looks like
.586
.model flat ,c
.stack 100h
.data
.code
doit proc
mov eax, 8
mov ebx, 4
mov ecx, 6
mov edx, 12
add eax, ebx
add eax, edx
sub eax, ecx
doit endp
end
I would now please like to print or message box the values in these registrys so that i can know if the program works. Thx for the help

VariantClear releases VT_DISPATCH -vs- MSDN documentation

VS2015 C++ / Windows7 SP1
Considering the following code:
CComPtr<IFontDisp> m_pFont;
::OleCreateFontIndirect(&fdesc,IID_IFontDisp,(void**)&m_pFont);
VARIANT var = m_pFont; // PSEUDO CODE
after this,
var.vt = 9; //VT_DISPATCH
var.DISPATCH = "oleaut32.dll/IFontDisp"
So all looks fine.
Now I call
::VariantClear(var);
And I debug into (ASM), I found this:
74CB2EA6 nop
CFont::Release:
--> 74CB2EA7 sub dword ptr [esp+4],4
74CB2EAC jmp CFont::Release (74CB2E79h)
74CB2EAE nop
74CB2EAF nop
74CB2EB0 nop
Following the code:
CFont::Release:
--> 74CB2E79 mov edi,edi
74CB2E7B push ebp
74CB2E7C mov ebp,esp
74CB2E7E push esi
74CB2E7F mov esi,dword ptr [ebp+8]
74CB2E82 push edi
74CB2E83 lea eax,[esi+0A8h]
74CB2E89 push eax
74CB2E8A call dword ptr [__imp__InterlockedDecrement#4 (74C91298h)]
74CB2E90 mov edi,eax
74CB2E92 test edi,edi
74CB2E94 je CFont::Release+261h (74CB30DAh)
74CB2E9A mov eax,edi
74CB2E9C pop edi
74CB2E9D pop esi
74CB2E9E pop ebp
74CB2E9F ret 4
So as I see, it releases the COM interface.
But if I see MSDN doc about VariantClear:
if the variant to be cleared is a COM object that is passed by
reference, the vtfield of the pvargparameter is VT_DISPATCH | VT_BYREF
or VT_UNKNOWN | VT_BYREF. In this case, VariantClear does not release
the object. Because the variant being cleared is a pointer to a
reference to an object, VariantClear has no way to determine if it is
necessary to release the object. It is therefore the responsibility of
the caller to release the object or not, as appropriate.
According to this, it should not call release on the IFontDisp.
Can anybody explain what is going on here?
Thanks.

Where is relocation data stored in a PE file if not in the .reloc section?

I have the following program:
BITS 32
section .data
_num1: dd 5
section .text
global _start
_start:
push ebp
mov ebp, esp
mov eax, 9
add eax, [_num2]
sub eax, [_num1]
leave
ret
_num2: dd 7
Which assembles into the x86 instructions below:
0x00401000 <+0>: push ebp
0x00401001 <+1>: mov ebp,esp
0x00401003 <+3>: mov eax,0x9
0x00401008 <+8>: add eax,DWORD PTR ds:0x401016
0x0040100e <+14>: sub eax,DWORD PTR ds:0x402000
0x00401014 <+20>: leave
0x00401015 <+21>: ret
Now, the addresses of the sub and add instructions seems pretty fixed (absolute). Indeed, the VirtualAddress of the .data section is 0x2000, but what if the program doesn't load at its preferred address and relocation must be applied?
In this case, since the VirtualAddress's are RVA's, the sections remain relative to each other, but the addresses above are fixed.
How does the loader know that it must change these addresses to point to the proper data items?

Resources