Hello All!
I'm doing a MASM course and I got into this exercise.
I have this simple assembly code:
.386
.model flat,c
.data
quote byte "Machines do feel", 0
message byte SIZEOF quote DUP(0),0
.code
start proc
mov esi,0
mov ecx,SIZEOF quote
LP:
mov al,quote[esi]
mov message[esi],al
inc esi
loop LP
ret
start endp
end
And I want to write a C++ program that can "printf" the variable "message".
How can I do this?
I tryed to add:
mov eax, DWORD ptr [message]
To the ".asm" file to store the address of the message variable on the register returned by the function and then I wrote this program to try to printf the values:
#include <iostream>
extern "C" char *start();
int main(){
char *message = start();
for(int i = 0x0; i < sizeof(message)/sizeof(char); i++){
printf("%s", message[i]);
}
return 0x0;
}
But when I try to run it I get the error:
Unhandled page fault on read access to 6863614D at address 0040162E (thread 0024), starting debugger...
0024:err:seh:start_debugger Couldn't start debugger L"winedbg --auto 32 68" (2)
Can you please explain me how can I print the values of the ".asm" file "message" variable?
And can also show me different methods to do this?
Thank you so much, have a nice coding!
Related
I have a C++ project that calls a extern function located in a .asm (MASM) file. Is there any way I can inline the MASM code inside of the C++ file instead of having to having to use a seperate .asm file?
.asm file
.data
.code
ZwReadVirtualMemory proc
mov r10, rcx
mov eax, 3Fh
syscall
ret
ZwReadVirtualMemory endp
end
Here is the C++ file
#include "stdafx.h"
#include <Windows.h>
#include <iostream>
using namespace std;
extern "C" NTSTATUS ZwReadVirtualMemory(HANDLE hProcess, void* lpBaseAddress, void* lpBuffer, SIZE_T nSize, SIZE_T* lpNumberOfBytesRead = NULL);
int main() {
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, 14648);
if (!hProcess)
return EXIT_FAILURE;
int intBuffer = 0;
void* lpBaseAddress = 0;
SIZE_T lpNumberOfBytesRead = 0;
NTSTATUS status = ZwReadVirtualMemory(hProcess, (PVOID)0x10ad0000, &intBuffer, sizeof(int), &lpNumberOfBytesRead);
cout << "ZwRVM returned " << dec << status << endl;
cout << "intBuffer = " << dec << intBuffer << endl;
cout << "lpNumberOfBytesRead = " << lpNumberOfBytesRead << endl;
cin.get();
}
Certain C/C++ compilers support non-standard inline assembly blocks asm or __asm__. They can be used to incorporate portions of assembler code into regular functions or methods.
Your code sample clearly points at using a WinAPI (thus Windows as target platform) and Visual Studio as a compiler (stdafx.h being the most unportable piece). However, Visual Studio 2010 and later updates stopped supporting inline assembly for 64-bit targets: http://msdn.microsoft.com/en-us/library/4ks26t93%28VS.100%29.aspx
Your options:
Compile MASM file into a separate object file and link it later with the rest of the program.
Use Intel Compiler for Windows. It supports inline assembler and is meant to be a drop-in replacement for Microsoft compilers on Windows, however I do not know how much extra porting effort will be required.
The only bit from your assembler file that is not directly accessible from C/C+ is issuing the syscall machine instruction. If you find an intrinsic function for that instruction that is supported by MS VS, you can use it instead of an inline assembly block. However, I cannot find one here. Intel's intrinsics are no better.
I have done some experiments with shellcode execution in which I wrote my own shellcode, write it into the target program's memory in which I want it executed and execute it with either a new thread or thread hijacking.
This works well, but manually writing the shellcode is rather time consuming, therefore I am looking for a method to be able to write a function in C or C++ that will be completely self-contained once compiled. This means that any compiled function should be executable independently. This way I could directly write it into my target's program ready to execute with WriteProcessMemory for example. Pushing the shellcode would therefore be done with a code like this:
#include <Windows.h>
#include <iostream>
using namespace std;
BOOL MakeABeep() {
return Beep(0x500, 0x500);
}
DWORD MakeABeepEnd() { return 0; }
int main() {
DWORD pid = 0;
cout << "PID: ";
cin >> dec >> pid;
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
if (!hProcess) { cout << "OpenProcess failed GLE = " << dec << GetLastError() << endl; return EXIT_FAILURE; }
void* buf = VirtualAllocEx(hProcess, NULL, 4096, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if (!buf) { cout << "VirtualAllocEx failed GLE = " << dec << GetLastError() << endl; return EXIT_FAILURE; }
SIZE_T size = (DWORD64)MakeABeep - (DWORD64)MakeABeepEnd;
BOOL wpmStatus = WriteProcessMemory(hProcess, buf, MakeABeep, size, NULL);
if (!wpmStatus) { cout << "WriteProcessMemory failed GLE = " << dec << GetLastError() << endl; return EXIT_FAILURE; }
HANDLE hThread = CreateRemoteThread(hProcess, NULL, NULL, (LPTHREAD_START_ROUTINE)buf, NULL, NULL, NULL);
if (!hThread) { cout << "CreateRemoteThread failed GLE = " << dec << GetLastError() << endl; return EXIT_FAILURE; }
WaitForSingleObject(hThread, INFINITE);
VirtualFreeEx(hProcess, buf, 0, MEM_RELEASE);
return EXIT_SUCCESS;
}
If compiled with the default options of MSVC compiler, only a bunch of jmp instructions are copied, which seem to be a jump table. To avoid this problem, I disabled incremental linking in the compiler options and now any code in the function MakeABeep is properly copied, with the exception of calls to imported functions.
In my shellcode I pass the arguments as required by the calling convention and then I put the address of the function I want to call in the register rax and finally I call the function with call rax.
Is it possible to make the compiler generate something like that?
The key thing is that the generated binary has to have self-contained-only subroutines that could be executed independently.
For example, this is the assembly code generated for the function MakeABeep:
To be able to run it directly, instead of this mov rax, QWORD PTR [rip+0x?] the compiler should mov the full address of the Beep function into rax instead.
Please ignore the problems related to the modules possibly not loaded or loaded at a different address in the target program, I only intent to call functions in kernel32 and ntdll which are for sure loaded and at the same address in different processes.
Thank you for your help.
The compiler does not know the full address of the Beep function. The Beep function lives in kernel32.dll and this .DLL is marked as ASLR compatible and could in theory change its address every time you run the program. There is no compiler feature that lets you generate the real address of a function in a .DLL because such a feature is pretty useless.
One option I can think of is to use magic cookies that you replace with the correct function addresses at run time:
SIZE_T beepaddr = 0xff77ffffffff7001ull; // Magic value
((BOOL(WINAPI*)(DWORD,DWORD))beepaddr)(0x500, 0x500); // Call Beep()
compiles to
00011 b9 00 05 00 00 mov ecx, 1280 ; 00000500H
00016 48 b8 01 70 ff ff ff ff 77 ff mov rax, -38280596832686079 ; ff77ffffffff7001H
00020 8b d1 mov edx, ecx
00022 ff d0 call rax
You would then have to write a wrapper around WriteProcessMemory that knows how to lookup and replace these magic values with the correct address.
Some shell code will have its own mini implementation of GetModuleHandle and GetProcAddress where it looks up the module in the PEB module list and then searches the export directory. They often use a mini hashing function for the names so they don't have to deal with strings.
If you are injecting a large amount of code you will probably get tired of these hacks and just load a .DLL in the remote process like everyone else.
I'm trying to figure out how to use DB variables from ASM into Inline ASM C++
I have this ASM code:
filename db "C:\imagen.bmp"
eti0:
mov ah,3dh
mov al,0
mov dx,offset filename
int 21h
and in C++:
//ASCII of C:\imagen.bmp plus zero in the end because of int 21h
int filename=6758921051099710310111046981091120;
asm{
mov ah,3dh
mov al,0
mov dx,offset filename
int 21h
}
Is this is correct?
The type int can only hold a 16-bit signed integer and the number you tried to assign to filename is way outside its range. As int variables are two bytes long, they're not all that useful for storing file names. Instead you should store the name in an array of char like this:
char filename[] = "C:\\imagen.bmp";
The array will include a zero byte as its final element, as normal for strings in C++.
You could also replace entire thing with:
int handle;
_dos_open("C:\\imagen.bmp", 0, &handle);
I am working on a C++ and external asm code. It is a requirement for us to work with external ASM libraries. The problem is that, I am having difficulty passing the string from the c++ side to asm. I am sure I am making some mistake in accessing the string on the asm end.
I basically read from a text file, word - by - word. Then I want to pass each word onto the ASM side and process it for some statistics.
Suppose I retrieved a word from the file and it is stored in
string wordFromFile = "America";
processWord(wordFromFile, wordFromFile.size()) //processFromWord is the ASM side function
;;ASM SIDE
;;The doubt I have (first of all all) is how do I declare the arguments on the ASM SIDE
ProcessWordUpperCase PROC C, wordFile :BYTE, len :DWORD
OR
ProcessWordUpperCase PROC C, buffer :DWORD, len :DWORD
How should I? And one more thing, in the function I am going to access the string by each letter. What do you advise here?
Here is a skeleton just counting the length of the string where you could put youir code.
toupper.cpp
extern "C"
{
int ProcessWordUpperCase(const char *wordFile, int arraySize);
};
int main(int argc, char*arg[])
{
char t[100];
int res;
res = ProcessWordUpperCase(t, sizeof(t));
std::string s = "myvalue";
res = ProcessWordUpperCase(s.c_str(), s.length());
return 0;
}
toupper.asm
.486
.model flat, C
option casemap :none
.code
ProcessWordUpperCase PROC, wordFile:PTR BYTE, arrayLen:DWORD
LOCAL X:DWORD
push ebx
push esi
push edi
mov edi, wordFile
xor eax, eax
dec edi
dec eax
##StringLoop:
inc edi
inc eax
cmp byte ptr [edi], 0
jne ##StringLoop
; return length of string
pop edi
pop esi
pop ebx
ret
ProcessWordUpperCase ENDP
END
A simple trick to get the skeleton of a function is to tell VS to output ASM files.
How to do it:
Crete a new source file with an empty function that has the prototype you want
e.g. int foo(const char* s, int bar) { return *s + bar; }
Right click on the a source file and select Properties->C/C++->Output Files->Assembler Output.
Select a value that suits you.
build and look at the generated ASM file.
The generated asm file includes some security checks that can disable by playing with the compilation flags for this file.
From the C side:
I'd do it like that: pass the string as an array, alongside with a number of fields in the array. The program will write the pointer to the very beginning of the array to the stack, so if you want to retrieve the very first char in the string, just refer to it as
mov eax, [adress of the pointer on stack]
What I am doing is injecting a DLL into a running process. I then proceed to check some informations about that process, such as versions etc. My problem is I cannot seem to access a string in the assembly file, that contains the revision number I want to doublecheck. Here is what I have so far:
__declspec(naked) void CheckBuild()
{
char* revision;
__asm {
sub esp, __LOCAL_SIZE
pushad
pushfd
mov revision, dword ptr 0x5F5200
}
printf("Detected revision ID: %u\n", revision);
__asm {
popfd
popad
add esp, __LOCAL_SIZE
retn
}
}
For this training stuff, the address of the string, that I get through IDA and that I checked using CheatEngine and OllyDbg, is constant.
However, no matter what I try, I always get 0x5F5200 back in decimal, which is definitely not what I expect. I almost tried everything, including lea and others, but I still don't get the valid string.
Can anyone point me to the correct direction ?
you are missing the "dereferencing":
mov revision, dword ptr [0x5F5200]
which isn't a valid instruction since it has two indirects, so
mov eax, dword ptr [0x5F5200]
mov revision, eax
if the value is indeed a string, there's something else wrong:
if the string is stored at 0x5F5200, you would simply use
printf("Detected revision ID: %s\n", 0x5F5200)
if the address of the string is stored at 0x5F5200, you would use
printf("Detected revision ID: %s\n", revision)
String format
If the string is unicode, you would use
printf("Detected revision ID: %S\n", revision);
(note that with wprintf, it's the other way 'round: %s for a wide character string, and %s for a char string).
Finally, if the string is not guaranteed to be zero-terminated but has a fixed length, you need to copy from the address to a local buffer and ensure zero termination before the print.