I am given this assignment:
This program is supposed to search an array of bytes for the value 0xf2. When it finds 0xf2, it should save its location (i.e. address) into the integer variable “f2Address”. If it does not find the value of 0xf2 in the array, it should put a value of 0x00 into the variable “f2Address”. This program has some bugs in it. Fix this program so that it does work properly.
The original code given was:
.label TABLE1_LOC_START
TABLE1 .byte 0xff,0xfe,0xfd,0xfc,0xfb,0xfa,0xf9,0xf8,0xf7,0xf6,0xf5,0xf4,0xf3,0xf2,0xf1,0xf0
TABLE1_ST .word TABLE1_LOC_START
RESET mov.w #0280h,SP
mov.w #WDTPW+WDTHOLD,&WDTCTL ; stop watchdog timer
mov &TABLE1_ST, R10
mov #0xf2, R11
mov #0x08, R12
again inc R10
cmp 0(R10), R11
je found
dec R12
jz again
found mov R10, &f2Address
endProgram jmp endProgram
In an attempt to solve this problem I changed the 'je' to 'jeq' and I added 'mainLoop' to the code. After my modifications I had this code:
.label TABLE1_LOC_START
TABLE1 .byte 0xff,0xfe,0xfd,0xfc,0xfb,0xfa,0xf9,0xf8,0xf7,0xf6,0xf5,0xf4,0xf3,0xf2,0xf1,0xf0
TABLE1_ST .word TABLE1_LOC_START
mainLoop mov &TABLE1_ST, R10
mov #0xf2, R11
mov #0x08, R12
again inc R10
cmp R10, R11
jeq found
dec R12
jnz again
found mov R10, &f2Address
endProgram jmp endProgram
When I step through it, R12 eventually decrements to zero. Once it does, it means that the value of 0xf2 wasn't found, so it should place a 0x00 in the 'f2Address'. But instead of placing a zero there, it simply keeps on moving through the instructions without changing/adding any values anywhere.
I am not quite sure what to do or where to go next from here. It is using CodeComposer on the MSP430.
Figured it out:
mainLoop mov &TABLE1_ST, R10
mov #0xf2, R11
mov #0x10, R12
again inc R10
cmp 0(R10), R11
jeq found
dec R12
jnz again
mov #0x00, &f2Address
found mov R10, &f2Address
endProgram jmp endProgram
Related
I am trying to write a little function to print either a null-terminated or fixed-length string in a specific memory location. Here is my code:
vbrstart:
xor eax, eax
mov sp, 0x7a00
mov bp, 0x6000
mov ss, ax
mov ds, ax
mov es, ax
xor ebx, ebx
xor ecx, ecx
push strict dword initializing
push strict word 0x0000
call printmsg
jmp end
;push strict dword memloc
;push strict word length
;call printmsg
printmsg:
pop strict dword [store_ret]
mov [store_cx], cx
mov [store_esi], esi
pop cx
pop esi
push eax
push ebx
mov ah, 0x0E
mov bx, 0x0007
cmp cx, 0x0000
je printnullterm
printgivenlen:
lodsb
cmp cx, 0x0000
je printdone
int 10h
dec cx
jmp printgivenlen
printnullterm:
lodsb
cmp al, 0x00
je printdone
int 10h
jmp printnullterm
printdone:
pop ebx
pop eax
mov esi, [store_esi]
mov cx, [store_cx]
push strict dword [store_ret]
ret
printdata:
store_cx dw 0
store_esi dd 0
store_ret dd 0
end:
hlt
jmp end
initializing db 10,13,'Initializing...',0
When tested, it prints indefinately, and doesn't stop at the null byte. Where did I make a mistake?
I see 2 problems with your code:
You've written a bootloader. Such a program runs in the 16-bit real address mode. This implies that the return address from a call will be a word and not a dword like your code is expecting.
printmsg:
pop word [store_ret]
You setup the stack in a risky manner. You need to first change the SS register and immediately after that the SP register.
xor ax, ax
mov ss, ax <<< Keep these together
mov sp, 0x7a00 <<< and in this order!
Since this is 16-bit code there's no need to push/pop the address as a dword.
push word initializing
...
pop si
Your stack is not properly aligned with all that pushes and pops. Check parameters passing and it's usage in the routine.
To start, here's a hint:
vbrstart:
xor eax, eax
mov sp, 0x7a00
mov bp, 0x6000
mov ss, ax
mov ds, ax
mov es, ax
xor ebx, ebx
xor ecx, ecx
push strict dword initializing
push strict word 0x0000
call printmsg ; near call, only 16 bits ret addr stored
jmp end
;push strict dword memloc
;push strict word length
;call printmsg
printmsg:
pop strict dword [store_ret] ; pop dword (ret address + 16 bits- 1st argument)
mov [store_cx], cx ; store_cx = 0
mov [store_esi], esi ; store_esi = ??
pop cx ; cx = initializing
. . .
I am recoding puts using nasm (64bit), and when puts receives NULL as argument it prints (null). I'm trying to recreate that behaviour, except I can't get the code to jump to the part where it prints (null). Instead it just prints nothing
here's my code:
global _my_puts
section .text
%define WRITE 0x2000004
%define STDOUT 1
_my_puts:
cmp rdi, 0
je is_null
mov r8, rdi
cmp byte [r8], 0
jne print_and_add
print_and_add:
mov rax, WRITE
mov rdi, STDOUT
mov rsi, r8
mov rdx, 1
syscall
inc r8
cmp byte [r8], 0
jne print_and_add
mov rax, WRITE
mov rdi, STDOUT
mov rdx, newline.len
lea rsi, [rel newline]
syscall
mov rax, 1
ret
is_null:
mov rax, WRITE
mov rdi, STDOUT
lea rsi, [rel nullmsg]
mov rdx, nullmsg.len
syscall
mov rax, 1
ret
section .data
nullmsg: db "(null)", 10
.len: equ $ - nullmsg
newline: db 10
.len: equ $ - newline
I also tried
test rdi, rdi
je is_null
with no change. Any ideas?
thanks for the help :)
Your first instruction is the problem: cmp rdi, 0. You're comparing the string pointer, passed to my_puts, to the value 0 to determine if you should print "(null)" rather than comparing the first byte of the string to 0. I'm supposing if you pass a 0 pointer, that would be an error.
Try:
_my_puts:
mov r8, rdi
cmp [r8], 0
je is_null
print_and_add:
...
If you want the defensive check against a 0 pointer, you could include that as well, but you wouldn't be checking against any other bad pointers:
_my_puts:
cmp rdi, 0
je bad_pointer
mov r8, rdi
cmp [r8], 0
je is_null
print_and_add:
...
I am working on this homework assignment, and my professor is stumped (as I am too) on why my array address refuses to load into R2. He said my code is correct, but he is absolutely uncertain about why it is behaving this way. It used to load 10 constantly, however, under the branch manageArray:, it should be overwriting the old use of R2. I even tried re-initializing the value, and it never worked.
We have run it under ARMSim, and code it as a .s file under notepad++. If anyone can point out what the potential cause is and why (because I absolutely want to learn from this, not look for answers!), I would be forever in your debt!! We have sat for nearly an hour and sent back so many emails over this, we're just frustrated and lost on where to go. It always loads a value of 10 or 11, but never the array address.
This is my code as of now. Basically, it's meant to check for odds (and terminate if true), else, add all of the array and print that total out. Semi-colons (;) are comments in assembly, which is weird.
.data
oddPrompt: .asciz "This Array is odd: we are terminating this thing.\n\r"
.align
terminatedPrompt: .asciz "YOU HAVE BEEN TERMINATED!\n\r"
.align
totalPrompt: .asciz "Total : \n\r"
.align
arrayLength = 10
;determineArrayOdds = arrayLength
array: .skip arrayLength*4
.text
mov r0,#0
mov r1,#0
mov r2,#arrayLength
mov r3,#0
mov r6,#0 ;element 1
mov r7,#0 ;element 2
mov r8,#0 ;added values from R7 and R6
mov r9,#0 ;grandTotal
verifyOdds:
sub r2, r2, #2
cmp r2,#2
blt errorForOdd
bgt verifyOdds
beq manageArray
errorForOdd:
;It's odd, so we skip calculating, because we never hit 2
mov r0,#1
ldr r1,=oddPrompt
swi 0x69
swi 0x11
manageArray:
ldr r2,=array
loop:
;Here, populate and add array elements.
;R2 will be re-purposed for this to conserve space.
swi 0x6d
and r0,r0,#0xff ;get time tick UP to 255 (via hex)
mov r1,r0
mov r0,#1
;swi 0x6b
str r1,[r2],#4
cmp r4,#arrayLength
addlt r4,r4,#1
blt loop ;ORIGINAL 49, now 50
moveq r4,#0
ldreq r2,=array
beq addArray
addArray:
ldrlt r6,[r2,#0] ;element 1
ldrlt r7,[r2,#4] ;element 2
add r2,r2,#8
add r8,r7,r6 ;store to r8
;mov r9,r8
add r9,r8,r9
cmp r4,#arrayLength
addlt r4,r4,#1
blt addArray
beq total
total:
mov r0,#1
ldr r1,=totalPrompt
swi 0x69
mov r1,r9 ;r1 has to hold the total to print
mov r0,#1 ;r0 must be set to true
swi 0x6b ;PRINT TOTAL NOW
swi 0x11
terminate:
mov r0,#1
ldr r1,=terminatedPrompt
swi 0x69
swi 0x11
I've written this procedure in asm:
.586
.model flat, stdcall
.xmm
.data
.code
EncryptAsm proc plainText:ptr byte, heigth:DWORD, inputLength:DWORD, encryptedText:ptr byte, cipherArray:ptr byte
local addRow:WORD
local row:DWORD
local column:DWORD
local iterator:DWORD
local forLoopIteratorI:DWORD
local forLoopIteratorJ:DWORD
push esi
push edi
push ebx
push ecx
push edx
mov addRow,0
mov row,0
mov column,0
mov iterator,0
mov forLoopIteratorI,0
mov forLoopIteratorJ,0
mov ecx,heigth
FILL_CIPHER_ARRAY_LOOP: mov eax, inputLength
cmp iterator,eax
jge PREPARE_ITERATOR
push ecx ;pushing heigth value
mov ecx,row ;calculating index of cipher array index=[row*inputLength+column]
imul ecx,inputLength
add ecx,column
mov eax,iterator
mov edx,plainText
mov al,[edx+eax]
mov [esi],al
mov ebx, cipherArray
mov [ebx+ecx],al
movsb
pop ecx;getting back heigth value
add column,1
cmp addRow,0
je INC_ROW
cmp addRow,0
jne DEC_ROW
INC_ROW: add row,1
jmp ROW_COMPARE
DEC_ROW: sub row,1
jmp ROW_COMPARE
ROW_COMPARE: cmp row,ecx
jge IF_STATEMENT_1
cmp row,0
jl IF_STATEMENT_2
jmp INCREMENT_ITERATOR
IF_STATEMENT_1: sub row,2
mov addRow,1
jmp INCREMENT_ITERATOR
IF_STATEMENT_2: add row,2
mov addRow,0
jmp INCREMENT_ITERATOR
INCREMENT_ITERATOR: add iterator,1
jmp FILL_CIPHER_ARRAY_LOOP
PREPARE_ITERATOR: mov iterator,0
READ_CIPHER_ARRY_LOOP_I:cmp forLoopIteratorI,ecx
jge PREPARE_ITERATOR_2
READ_CIPHER_ARRY_LOOP_J:mov eax, inputLength
cmp forLoopIteratorJ,eax
jge PREPARE_I_AND_J
push ecx ;pushing heigth value
mov ecx,forLoopIteratorI ;calculating index of cipher array
imul ecx,inputLength
add ecx,forLoopIteratorJ
mov ebx,cipherArray
mov al,[ebx+ecx]
cmp al,'#'
jne COPY_VALUE
ITERATE: add forLoopIteratorJ,1
pop ecx
jmp READ_CIPHER_ARRY_LOOP_J
PREPARE_I_AND_J: mov forLoopIteratorJ,0
add forLoopIteratorI,1
jmp READ_CIPHER_ARRY_LOOP_I
COPY_VALUE: push edi
mov edi,iterator
mov edx,encryptedText
mov [edx+edi],al
add iterator,1
pop edi
jmp ITERATE
PREPARE_ITERATOR_2: mov iterator,0
FINISH: mov eax, encryptedText
pop edx
pop ecx
pop ebx
pop edi
pop esi
ret
EncryptAsm endp
end
It implements rail fence cipher algorithm (at the end the variable encryptedText contains ciphered plainText). It works fine, I mean it does the encryption well but after all I'm getting memory corrupt error... I'm calling this procedure as an extern one from C app. I can print the encrypted text without any problem but when returning 0 in main function, the memory corrupt error pops up.
I don't know what can cause it. At the beginning of asm procedure, I push all the registers' values and pop them after the whole operation.
The error message:
Unhandled exception at 0x72676F74 in ConsoleApplication12.exe: 0xC0000005: Access violation executing location 0x72676F74.
I'll be greatful for any hint.
One possible candidate could be here:
mov edx,plainText
mov al,[edx+eax]
mov [esi],al
esi is pushed, from the caller, but where is it initialized? It seems that it uses whatever is there from the caller. Same for edi so where will movsb store it?
UPDATE
Since I don't know your algorithm and don't see how it is used I can only guess. BUt I think you should do the following before the loop:
mov esi, plainText
mov edi, encryptedText
mov ebx, cipherArray
Since you don't change these values you can then change this code:
COPY_VALUE: push edi
mov edi,iterator
mov edx,encryptedText
mov [edx+edi],al
add iterator,1
pop edi
jmp ITERATE
to this:
COPY_VALUE: mov edx,iterator
mov [edx+edi],al
inc iterator
jmp ITERATE
Generally instead of using add x, 1 you can use inc x which is shorter.
People I've found it! The cause of the error was... 'movsb'. I was using it in a previous version of my algorithm and I've forgotten to delete it... The rest of my code works fine. Thanks for all the answers and for willing to help m ;)
For a security class I am supposed to write self-modifying code for a program which finds its own executable on the disk, reads the binary data, and encrypts part of it before writing it back out to the disk. This is supposed to be like a polymorphic virus which changes itself to fool antivirus scanners which detect known signatures.
I have all the pieces pretty much in place:
I am finding the executable using /proc/self/exe.
I am using a simple AES implementation to encrypt 16 byte string in some dummy code in the executable.
I am able to read the binary data in and locate the part I need to encrypt.
My problem is that the only way I have been able to open the executable is in read-only mode "rb". If I try to open the file for writing in mode "wb" or "r+b" I get back the error "Text file busy". Is there anyway for me to write to a process's own executable in C? Can I do this by changing the permissions somehow?
EDIT: What I am trying to accomplish is to have an executable which will encrypt part of itself each time that it runs so that it will have a new checksum after every time it runs.
After reading data from the executable binary, how can I either write back to it or remove it and replace it with a new file with the same filename?
You cannot write to a file that is currently mapped as an executable. However, you can write to a file that has the same path as the current executable, so long as it isn't actually the same file — try unlinking the file you're being executed from and creating a new file in its place, for instance.
In order to do self modification too, I wrote a small code in nasm (which can be used as a stub), which opens itself and at the middle of the code (right after the mmap), we have a pointer which points to the bytes of the executable that we can modify.
The code looks like this:
BITS 64
section .text
global _start
_start:
call _main__
mov rax, 60
mov rdi, 0x0
syscall ; exit(0);
_main__:
push rbp
mov rbp, rsp
sub rsp, 144 ; stat_file
mov rdi, [rbp+0x18]
lea rsi, [rsp]
call _open_self ; open self
push r12 ; len file
push rax ; addr
mov r14, rsi
mov rdi, [rbp+0x18] ; pathname
pop rsi ; addr
pop rdx ; len
push rdx
push rsi
call __create
mov r13, rax ; second fd
mov rdi, r14 ; fd
pop rsi ; addr -> mmap
pop rdx ; len_file
call __close_unmap
mov rax, 87
mov rdi, [rbp+0x18]
syscall
mov rax, 0x3 ; close(scnd_fd);
mov rdi, r13
syscall
mov rax, 86
push 'nasm'
lea rdi, [rsp]
mov rsi, [rbp+0x18]
syscall ; link tmp name to original name
mov rax, 87
lea rdi, [rsp]
syscall ; delete old tmp file
leave
ret
; ===============================
; Open himself
_open_self:
push rbp
mov rbp, rsp
mov r15, rsi ; &stat_file
mov r12, rdi ; *pathname
mov rax, 0x2
mov rsi, 0x0 ; 0_RD
mov rdx, 509
syscall
push rax ; fd
mov rdi, rax ; fd
mov rsi, r15 ; struct stat
mov rax, 5 ; fstat
syscall
xor rdi, rdi
mov rsi, qword [r15+48]
mov rdx, 0x4
mov r10, 0x2
pop r8
push r8
mov r9, 0x0
mov rax, 9
syscall ; mmap
; rax -> byte of the executable that we gonna dump
mov r12, qword [r15+48]
pop rsi ; fd
leave
ret
; ===============================
; int __create(const char *pathname, void *addr, ssize_t len_bytes_mapped);
__create:
push rbp
mov rbp, rsp
push rsi ; addr
push rcx ; len
push 'nasm'
lea rdi, [rsp]
mov rax, 0x2
mov rsi, 0x42 ; 0_CREAT | O_RDWR
mov rdx, 509
syscall ; sys_open
add rsp, 0x8 ; 'nasm'
mov r9, rax ; fd
mov rdi, rax ; fd
mov rax, 0x1
pop rdx
pop rsi
syscall ; sys_write
mov rax, r9 ; fd final
leave
ret
; int __close_unmap(int fd, unsigned lon addr, ssize_t len_file);
__close_unmap:
push rbp
mov rbp, rsp
push rdi
mov rdi, rsi
mov rsi, rdx
mov rax, 11
syscall ; munmap(addr, len_file)
pop rdi
mov rax, 3
syscall ; close(fd);
leave
ret
It is a bit long but it makes just :
-Open it self in read mode (O_RD == 0x0)
-Do a stat(*pathname, &buffer_struct_stat);
-And then a mmap(0, buffer_struct_stat.st_size, 0x4, MAP_PRIVATE, fd_read_only, 0);
-Here you can edit your executable by editing the bytes at the address returned by mmap
-Create a tmp file named "nasm"
-Do a write(fd_tmp, address_of_mmap, buffer_struct_stat.st_size)
-Close the two file descriptors and munmap the mmap
-Now it's cool : unlink(pathname) and link("nasm", "pathname")