Visual C++ inline assembly char* - visual-c++

I need to edit a string received from user in C++ code in assembly. I found this tutorial http://msdn.microsoft.com/en-US/library/y8b57x4b(v=vs.80).aspx and according to it my code should work
int main ()
{
char* s;
s=new char[80];
cin.getline(s,80);
__asm
{
mov eax, offset s
}
}
But the compiler shows an error on the line with mov "improper operand type". What is wrong and how can i fix it?

char* s is a local variable. It will be created when the function is called and "forgotten" when the function returns. There exists no "offset" (i.e an absolute memory address) for it at compiletime. But you can inline-assembler force to load the pointer:
#include <iostream>
using namespace std;
int main ()
{
char* s;
s=new char[80];
__asm
{
mov ebx, s ; = mov ebx, [ebp-4]
mov byte ptr [ebx], 'H'
mov byte ptr [ebx+1], 'e'
mov byte ptr [ebx+2], 'l'
mov byte ptr [ebx+3], 'l'
mov byte ptr [ebx+4], 'o'
mov byte ptr [ebx+5], 0 ; Don't forget the terminator!
}
cout << s << endl;
return 0;
}

Related

A simple function to square a number in assembly

My second day into assembly programming, I am trying to create a function to square a number
square.asm:
global square: ; do not need _start because gcc has one already
section .text
square:
mov rax, rsi; remember: first argument is always in rsi. (Order is: rsi, rdi, rdx, tcx, r8, r9)
mul rsi ; rax = rax * rsi (remember: accumulator is the implicit argument)
ret ; returns the value in accumulator
main.c:
#include <stdio.h>
long int square(long int);
int main() {
for (long int i = 1; i < 6; i++) {
printf("%li", square(i));
}
return 0;
}
result:
7556421251850319424-3765949904798924751-3765949904798924751-3765949904798924751-3765949904798924751
expected:
1491625
What have I missed?
Your first parameter is in rdi, not rsi, if you're using the System V ABI.
Use:
mov ras, rdi
mul rdi
ret
To make the output easier to read, you'll also want some whitespace or a newline in your print statement:
printf("%li\n", square(i));
And one nitpick - use either int main(void) or int main(int argc, char **argv) for your main function signature. Anything else is undefined.

Unexpected character in the filename I'm writing to

My problem is related with Assembler and Shellcoding.
I started off by writing my first shellcode and it worked out pretty well so far. I then made an assembly script of the following C code:
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
int main()
{
int fd = open("test.txt", O_CREAT | O_WRONLY);
write(fd, "Hello World!", 6);
return 0;
}
The assembly code for that piece looks like this:
global _start
_start:
xor eax, eax ; null eax reg
push 0x7478742e ; push "test.txt" on stack
push 0x74736574
mov ebx, esp ; first Argument
mov cl, 0x41 ; Flags O_CREAT | O_WRONLY
mov al, 0x5 ; sys_open
int 0x80
push 0x736b6330 ; "shellcodingr0cks"
push 0x72676e69
push 0x646f636c
push 0x6c656853
mov ebx, eax ; file identifier
mov ecx, esp ; string on the stack
mov dl, 0x10 ; 0x10 is the size of the string
mov al, 0x4 ; sys_write
int 0x80
xor eax, eax ; exit proc
inc eax
int 0x80
The Program works pretty well and I've got the expected output but there is one problem and I don't know why this is occurring.
The filename of the file I'm writing to should be test.txt but it is writing to test.txt^A. I don't know where the ^A is coming from, nor do I know how to fix it.
Does anyone know what is wrong, and how I can fix it?

(VC++) Runtime Check for Uninitialized Variables: How is the test Implemented?

I'm trying to understand what this test does exactly. This toy code
int _tmain(int argc, _TCHAR* argv[])
{
int i;
printf("%d", i);
return 0;
}
Compiles into this:
int _tmain(int argc, _TCHAR* argv[])
{
012C2DF0 push ebp
012C2DF1 mov ebp,esp
012C2DF3 sub esp,0D8h
012C2DF9 push ebx
012C2DFA push esi
012C2DFB push edi
012C2DFC lea edi,[ebp-0D8h]
012C2E02 mov ecx,36h
012C2E07 mov eax,0CCCCCCCCh
012C2E0C rep stos dword ptr es:[edi]
012C2E0E mov byte ptr [ebp-0D1h],0
int i;
printf("%d", i);
012C2E15 cmp byte ptr [ebp-0D1h],0
012C2E1C jne wmain+3Bh (012C2E2Bh)
012C2E1E push 12C2E5Ch
012C2E23 call __RTC_UninitUse (012C10B9h)
012C2E28 add esp,4
012C2E2B mov esi,esp
012C2E2D mov eax,dword ptr [i]
012C2E30 push eax
012C2E31 push 12C5858h
012C2E36 call dword ptr ds:[12C9114h]
012C2E3C add esp,8
012C2E3F cmp esi,esp
012C2E41 call __RTC_CheckEsp (012C1140h)
return 0;
012C2E46 xor eax,eax
}
012C2E48 pop edi
012C2E49 pop esi
012C2E4A pop ebx
012C2E4B add esp,0D8h
012C2E51 cmp ebp,esp
012C2E53 call __RTC_CheckEsp (012C1140h)
012C2E58 mov esp,ebp
012C2E5A pop ebp
012C2E5B ret
The 5 lines emphasized are the only ones removed by properly initializing the variable i. The lines 'push 12C2E5Ch, call __RTC_UninitUse' call the function that display the error box, with a pointer to a string containing the variable name ("i") as an argument.
What I can't understand are the 3 lines that perform the actual test:
012C2E0E mov byte ptr [ebp-0D1h],0
012C2E15 cmp byte ptr [ebp-0D1h],0
012C2E1C jne wmain+3Bh (012C2E2Bh)
It would have seemed the compiler is probing the stack area of i (setting a byte to zero and immediately testing whether it's zero), just to be sure it isn't initialized somewhere it couldn't see during build. However, the probed address, ebp-0D1h, has little to do with the actual address of i.
Even worse, it seems if there were such an external (other thread?) initialization that did initialize the probed address but to zero, this test would still shout about the variable being uninitialized.
What's going on? Maybe the probe is meant for something entirely different, say to test if a certain byte is writable?
[ebp-0D1h] is a temporary variable used by the compiler to track "initialized" status of variables. If we modify the source a bit, it will be more clear:
int _tmain(int argc, _TCHAR* argv[])
{
int i, j;
printf("%d %d", i, j);
i = 1;
printf("%d %d", i, j);
j = 2;
return 0;
}
Produces the following (irrelevant parts skipped):
mov DWORD PTR [ebp-12], -858993460 ; ccccccccH
mov DWORD PTR [ebp-8], -858993460 ; ccccccccH
mov DWORD PTR [ebp-4], -858993460 ; ccccccccH
mov BYTE PTR $T4694[ebp], 0
mov BYTE PTR $T4693[ebp], 0
In prolog, variables are filled with 0xCC, and two tracking variables (one for i and one for j) are set to 0.
; 7 : printf("%d %d", i, j);
cmp BYTE PTR $T4693[ebp], 0
jne SHORT $LN3#main
push OFFSET $LN4#main
call __RTC_UninitUse
add esp, 4
$LN3#main:
cmp BYTE PTR $T4694[ebp], 0
jne SHORT $LN5#main
push OFFSET $LN6#main
call __RTC_UninitUse
add esp, 4
$LN5#main:
mov eax, DWORD PTR _j$[ebp]
push eax
mov ecx, DWORD PTR _i$[ebp]
push ecx
push OFFSET $SG4678
call _printf
add esp, 12 ; 0000000cH
This corresponds roughly to:
if ( $T4693 == 0 )
_RTC_UninitUse("j");
if ( $T4694 == 0 )
_RTC_UninitUse("j");
printf("%d %d", i, j);
Next part:
; 8 : i = 1;
mov BYTE PTR $T4694[ebp], 1
mov DWORD PTR _i$[ebp], 1
So, once i is intialized, the tracking variable is set to 1.
; 10 : j = 2;
mov BYTE PTR $T4693[ebp], 1
mov DWORD PTR _j$[ebp], 2
Here, the same is happening for j.
Here is my guess: the compiler probably allocates flags in memory showing the initialization status of variables. In your case for variable i this is a single byte at [ebp-0D1h]. The zeroing of this byte means i is not initialized. I assume if you initialize i this byte will be set to non-zero. Try something run-time like this: if (argc > 1) i = 1; This should generate code instead of omitting the whole check. You can also add another variable, and see if you get two different flags.
The zeroing of the flag and the testing just happen to be consecutive in this case, but that might not always be the case.
C7060F000055 mov dword ptr [esi],5500000Fh
C746048BEC5151 mov dword ptr [esi+0004],5151EC8Bh
b. And one of its later generations:
BF0F000055 mov edi,5500000Fh
893E mov [esi],edi
5F pop edi
52 push edx
B640 mov dh,40
BA8BEC5151 mov edx,5151EC8Bh
53 push ebx
8BDA mov ebx,edx
895E04 mov [esi+0004],ebx
c. And yet another generation with recalculated ("encrypted") "constant" data:
BB0F000055 mov ebx,5500000Fh
891E mov [esi],ebx
5B pop ebx
51 push ecx
B9CB00C05F mov ecx,5FC000CBh
81C1C0EB91F1 add ecx,F191EBC0h ; ecx=5151EC8Bh

Replace a character in a string using assembly code in MASM

So my program is very simple. I have a string "Hello World" and I want to replace 'H' with 'A'. So here is my assembly code for MASM.
char* name = "Hello World";
_asm
{
mov eax, name;
mov ebx, 'A';
mov [eax], ebx;
}
printf("%s", name);
Visual Studio cannot compile this. It alerts me that this program is not working. I suspect my syntax for mov[eax], ebx might be wrong. All comments are appreciated. Thanks!
Here is the image of the alert: https://www.dropbox.com/s/e5ok96pj0mxi6sa/test%20program%20not%20working.PNG
"Hello World" is a literal, i.e a non-writeable constant string. 'name' is a pointer which points to that literal. You can instead define an array, which has to be populated with that literal, i.e. the literal is copied into the array:
#include <stdio.h>
int main (void)
{
char name[] = "Hello World";
_asm
{
lea eax, name; // EAX = address of name
mov ebx, 'A';
mov [eax], bl;
}
printf("%s", name);
return 0;
}
The original code works, if you use the C89-Compiler of MSVC (file-extension .c or command line option /TC), but that does not really meet the standard.
First Character
mov eax, _name; // EAX = address of name
mov bl, 'A';
mov byte[eax], bl;
Second Character
mov eax, _name; // EAX = address of name
mov bl, 'A';
mov byte[eax+1], bl;
MOVS
MOVS - This instruction moves 1 Byte, Word or Doubleword of data from memory location to another.
LODS
LODS - This instruction loads from memory. If the operand is of one byte, it is loaded into the AL register, if the operand is one word, it is loaded into the AX register and a doubleword is loaded into the EAX register.
STOS
STOS - This instruction stores data from register (AL, AX, or EAX) to memory.
CMPS
CMPS - This instruction compares two data items in memory. Data could be of a byte size, word or doubleword.
SCAS
SCAS - This instruction compares the contents of a register (AL, AX or EAX) with the contents of an item in memory.

Modifying a character array, the modified part shows up backwards

I have just started learning assembly, and I am trying to modify a character array.
This is my assembly code:
.data
data byte 'Five', 0
.code
Asm proc
lea rax, data
mov dword ptr[rax], 'Four'
ret
Asm endp
end
And my C++ code:
#include <stdio.h>
#include <conio.h>
// external function
extern "C" char* Asm();
// main function
int main()
{
printf(Asm());
_getch();
}
When I comment out mov dword ptr[rax], 'Four', the result is that the console prints: "Five". But, with the above code uncommented, the result is "ruoF", instead of what I expected it to be, which is obviously "Four".
Why is this happening? How can I get the text to output in the correct direction without having to do some cheap workaround like this: mov dword ptr[rax], 'ruoF'?
You can use:
mov ebx,'Four'
bswap ebx
mov [rax],ebx
Or, on Intel Atom processors that support movbe (can be confirmed with cpuid):
mov ebx,'Four'
movbe [rax],ebx

Resources