This is the ASM code:
__declspec(naked) void foo(something* t)
{
__asm {
push ebp
mov ebp, esp
mov eax, dword ptr [t]
mov dword ptr [eax], 0
mov dword ptr [eax+4], 0
mov esp, ebp
pop ebp
}
This would be the C version of the code:
struct something {
_int64 a;
_int64 b;
_int64 c;
};
void foo(struct* something) {
something->a = 0;
}
Now, I am wonder if I could do the same thing without storing t in eax. And just use ebp instead. But I am not sure where "a" would be (ebp+28 or ebp), and if it is even possible. This doesn't seem to work. Does anyone if this is possible, and how?
mov dword ptr [ebp+28], 0
mov dword ptr [ebp+24], 0
Arbitrary nesting of expressions is not possible in assembly. That's what high level languages were invented for. In other words, yes, you have to load the value of t into a register if you want to dereference it. Assembly does not support constructs like
mov dword ptr [[ebp+28]], 0
which is what you're aiming for. ebp+28 is not the address of t->a; it's the address of t, which is the address of t->a.
Also, the assembly snippet zeros out both t->a and t->b while the C one only does a. They're not equivalent.
Related
Hey so I was looking at the assembly code of a heap-overflow challenge (heap3 in protostar) in which use a vulnerability of an old version of dlmalloc to execute the exploit. Below is the assembler dump
0x08048889 <main+0>: push ebp
0x0804888a <main+1>: mov ebp,esp
0x0804888c <main+3>: and esp,0xfffffff0
0x0804888f <main+6>: sub esp,0x20
0x08048892 <main+9>: mov DWORD PTR [esp],0x20
0x08048899 <main+16>: call 0x8048ff2 <malloc>
0x0804889e <main+21>: mov DWORD PTR [esp+0x14],eax
0x080488a2 <main+25>: mov DWORD PTR [esp],0x20
0x080488a9 <main+32>: call 0x8048ff2 <malloc>
0x080488ae <main+37>: mov DWORD PTR [esp+0x18],eax
0x080488b2 <main+41>: mov DWORD PTR [esp],0x20
0x080488b9 <main+48>: call 0x8048ff2 <malloc>
0x080488be <main+53>: mov DWORD PTR [esp+0x1c],eax
0x080488c2 <main+57>: mov eax,DWORD PTR [ebp+0xc]
0x080488c5 <main+60>: add eax,0x4
0x080488c8 <main+63>: mov eax,DWORD PTR [eax]
0x080488ca <main+65>: mov DWORD PTR [esp+0x4],eax
0x080488ce <main+69>: mov eax,DWORD PTR [esp+0x14]
0x080488d2 <main+73>: mov DWORD PTR [esp],eax
0x080488d5 <main+76>: call 0x8048750 <strcpy#plt>
0x080488da <main+81>: mov eax,DWORD PTR [ebp+0xc]
0x080488dd <main+84>: add eax,0x8
0x080488e0 <main+87>: mov eax,DWORD PTR [eax]
0x080488e2 <main+89>: mov DWORD PTR [esp+0x4],eax
0x080488e6 <main+93>: mov eax,DWORD PTR [esp+0x18]
0x080488ea <main+97>: mov DWORD PTR [esp],eax
0x080488ed <main+100>: call 0x8048750 <strcpy#plt>
0x080488f2 <main+105>: mov eax,DWORD PTR [ebp+0xc]
0x080488f5 <main+108>: add eax,0xc
0x080488f8 <main+111>: mov eax,DWORD PTR [eax]
0x080488fa <main+113>: mov DWORD PTR [esp+0x4],eax
0x080488fe <main+117>: mov eax,DWORD PTR [esp+0x1c]
0x08048902 <main+121>: mov DWORD PTR [esp],eax
0x08048905 <main+124>: call 0x8048750 <strcpy#plt>
0x0804890a <main+129>: mov eax,DWORD PTR [esp+0x1c]
0x0804890e <main+133>: mov DWORD PTR [esp],eax
0x08048911 <main+136>: call 0x8049824 <free>
0x08048916 <main+141>: mov eax,DWORD PTR [esp+0x18]
0x0804891a <main+145>: mov DWORD PTR [esp],eax
0x0804891d <main+148>: call 0x8049824 <free>
0x08048922 <main+153>: mov eax,DWORD PTR [esp+0x14]
0x08048926 <main+157>: mov DWORD PTR [esp],eax
0x08048929 <main+160>: call 0x8049824 <free>
0x0804892e <main+165>: mov DWORD PTR [esp],0x804ac27
0x08048935 <main+172>: call 0x8048790 <puts#plt>
0x0804893a <main+177>: leave
0x0804893b <main+178>: ret
End of assembler dump.
Now looking at the assembler dump what I can understand is malloc and free are linked to the binary statically, while strcpy and puts are linked using PLT.
When I try to compile this program using it's source code, I get malloc#plt and free#plt, which when compiled on my local machine uses the wrong version of dlmalloc. The challenge is compiled and placed on a debian distro which we have to boot up in order to try this challenge but I would like to try it on my local machine. Can someone explain how I will be able to compile it so that malloc and free are statically linked with the binary.
I'd like to know, how to do the following.
I have an array, where i have to summ numbers (easy)
but the twist is, that i have to have a function call for it,
that get's is params through specific registers. How do i implement that?
In this case, the function needs to get the array (offset) through ESI, and the length of it through ECX.
please educate me
EDIT:
in the meantime i've conjured up this. No idea if this works to as my MASM compliling just broken itself for no reason
.data
intarray DWORD 10000h,20000h,30000h,40000h
.code
szummer proc uses esi ecx,
ptrArray:PTR DWORD, ;points to the array
szArray: Dword ;array size
mov esi, ptrArray ;address of the array
mov ecx, szArray ;szize
mov eax, 0 ;set to 0
AS1:
add eax, [esi] ;add each int to sum
add esi, 4 ;point to next int
loop AS1 ;reapet for array size
ret;
szummer endp
main proc
mov ecx, OFFSET intarray
mov esi, LENGHTOF intarray
INVOKE ArraySum,ecx,esi
invoke ExitProcess,0
main endp
end main
The MASM directive INVOKE works only with the calling conventions C (cdecl), STDCALL, BASIC, FORTRAN and PASCAL. All of these conventions pass the arguments on the stack. Thus, you can't use INVOKE for passing the arguments in registers. You can use the Assembly instruction CALL instead. Your program - slightly modified ;-) - with MASM32 library included (because of "ExitProcess"):
INCLUDE \masm32\include\masm32rt.inc
.DATA
intarray DWORD 10000h,20000h,30000h,40000h
.CODE
szummer proc uses esi ecx
mov eax, 0 ;set to 0
AS1:
add eax, [esi] ;add each int to sum
add esi, 4 ;point to next int
loop AS1 ;reapet for array size
ret;
szummer endp
main proc
mov esi, OFFSET intarray
mov ecx, LENGTHOF intarray
call szummer
invoke ExitProcess,0
main ENDP
END main
The instruction "push 0FFFFFFFFh" appears that just after a new stack frame within the callee is established,e.g.,
push ebp
mov ebp,esp
push 0FFFFFFFFh <===HERE //[ebp-4] is set to 0FFFFFFFFh
push 0255F58h // SEH EXCEPTION_REGISTRATION.handler
mov eax,dword ptr fs:[00000000h]
push eax // SEH EXCEPTION_REGISTRATION.prev
sub esp,0D8h
push ebx
push esi
push edi
lea edi,[ebp-0E4h]
mov ecx,36h // 36h * 0CCCCCCCCh
mov eax,0CCCCCCCCh
rep stos dword ptr es:[edi]
mov eax,dword ptr [__security_cookie (025A004h)]
xor eax,ebp
push eax
lea eax,[ebp-0Ch]
mov dword ptr fs:[00000000h],eax // Install new EXECEPTION_REGISTRATION
lea ecx,[intobj]
call A<int>::A<int> (0251389h)
mov dword ptr [ebp-4],0 //[ebp-4] is set to 0
call A<int>::PrintNum (025139Dh)
mov dword ptr [ebp-0E0h],0
mov dword ptr [ebp-4],0FFFFFFFFh //[ebp-4] is set to 0FFFFFFFFh again, then [ebp-4] keeps the value in this callee.
lea ecx,[intobj]
call A<int>::~A<int> (025138Eh)
mov eax,dword ptr [ebp-0E0h]
...
What's point of this instruction "push 0FFFFFFFFh"?
[C++ Source Code]
[UPDATE] Apr 4 2018
Using Windbg, I can make sure the instruction "push 0FFFFFFFFh"(see "Here" in disassembly code) is nothing with SEH, though I still don't know what's point of this instruction "push 0FFFFFFFFh"?
0:000> dd fs:[0] l4
0053:00000000 0046fec0 00470000 0046d000 00000000
0:000> dt _Exception_registration_record 0046fec0
test!_EXCEPTION_REGISTRATION_RECORD
+0x000 Next : 0x0046ff28 _EXCEPTION_REGISTRATION_RECORD <== eax
+0x004 Handler : 0x00255F58 _EXCEPTION_DISPOSITION test!__scrt_stub_for_acrt_uninitialize+0 <== 0255F58h
0:000> dt _Exception_registration_record 0x0046ff28
test!_EXCEPTION_REGISTRATION_RECORD
+0x000 Next : 0x0046ff84 _EXCEPTION_REGISTRATION_RECORD
+0x004 Handler : 0x00283100 _EXCEPTION_DISPOSITION test!_except_handler4+0
0:000> dt _Exception_registration_record 0x0046ff84
test!_EXCEPTION_REGISTRATION_RECORD
+0x000 Next : 0xffffffff _EXCEPTION_REGISTRATION_RECORD
+0x004 Handler : 0x77875845 _EXCEPTION_DISPOSITION ntdll!_except_handler4+0
Since SEH is a linked list there are actually two addresses.
The first one is the address of the next handler (in case of chaining) or 0xFFFFFFFF (-1) is this is the last one. The next one is the actual SE Handler.
An old but good read about SEH is "A Crash Course on the Depths of Win32™ Structured Exception Handling".
I'm getting this error when running program:
Access violation writing location 0x0105100b
Does anyone know what's wrong with this code? It's breaking at mov [ecx],dl
.686
.model flat
extern _ExitProcess#4: PROC
public _main
.data
.code
data1 db 61H,62H,63H,64H,65H,66H,67H,68H,69H,70H,0H
data2 db 25 dup (?)
_main:
mov eax, OFFSET data1
mov ecx, OFFSET data2
mov edx, 0
mov ebp, ecx
sub ebp, eax ; licznik
mov dl, BYTE PTR [eax]
mov [ecx],dl
koniec:
push 0
call _ExitProcess#4
END
I am trying to write a simple sum function in x86 assembly - to which i am passing 3 and 8 as arguments. However, the code doesn't print the sum. Appreciate any help in spotting the errors. I'm using NASM
section .text
global _start
_sum:
push ebp
mov ebp, esp
push edi
push esi ;prologue ends
mov eax, [ebp+8]
add eax, [ebp+12]
pop esi ;epilogue begins
pop edi
mov esp, ebp
pop ebp
ret 8
_start:
push 8
push 3
call _sum
mov edx, 1
mov ecx, eax
mov ebx, 1 ;stdout
mov eax, 4 ;write
int 0x80
mov ebx, 0
mov eax, 1 ;exit
int 0x80
To me, this looks like Linux assembler. From this page, in the Examples section, subsection int 0x80, it looks like ecx expects the address of the string:
_start:
movl $4, %eax ; use the write syscall
movl $1, %ebx ; write to stdout
movl $msg, %ecx ; use string "Hello World"
movl $12, %edx ; write 12 characters
int $0x80 ; make syscall
So, you'll have to get a spare chunk of memory, convert your result to a string, probably null-terminate that string, and then call the write with the address of the string in ecx.
For an example of how to convert an integer to a string see Printing an Int (or Int to String) You'll have to store each digit in a string instead of printing it, and null-terminate it. Then you can print the string.
Sorry, I have not programmed in assembly in years, so I cannot give you a more detailed answer, but hope that this will be enough to point you in the right direction.