Solving Binary Bomb Phase 5 [duplicate] - debugging

So I am working on a Binary Bomb assignment and have gotten stuck. Tried looking at other questions and guides but mine seems to be completely different from what is described in other questions and guides I found on the web.
The phase only takes 2 unsigned ints for input. Here it is disassembled in gdb after being run with 11 2 as input.
Dump of assembler code for function phase_5:
0x08048ccc <+0>: push %ebp
0x08048ccd <+1>: mov %esp,%ebp
0x08048ccf <+3>: push %esi
0x08048cd0 <+4>: push %ebx
=> 0x08048cd1 <+5>: sub $0x20,%esp
0x08048cd4 <+8>: lea -0x10(%ebp),%eax
0x08048cd7 <+11>: mov %eax,0xc(%esp)
0x08048cdb <+15>: lea -0xc(%ebp),%eax
0x08048cde <+18>: mov %eax,0x8(%esp)
0x08048ce2 <+22>: movl $0x8049b0a,0x4(%esp)
0x08048cea <+30>: mov 0x8(%ebp),%eax
0x08048ced <+33>: mov %eax,(%esp)
0x08048cf0 <+36>: call 0x8048788 <__isoc99_sscanf#plt>
0x08048cf5 <+41>: cmp $0x1,%eax
0x08048cf8 <+44>: jg 0x8048cff <phase_5+51>
0x08048cfa <+46>: call 0x80492b6 <explode_bomb>
0x08048cff <+51>: mov -0xc(%ebp),%eax
0x08048d02 <+54>: and $0xf,%eax
0x08048d05 <+57>: mov %eax,-0xc(%ebp)
0x08048d08 <+60>: cmp $0xf,%eax
0x08048d0b <+63>: je 0x8048d36 <phase_5+106>
0x08048d0d <+65>: mov $0x0,%ecx
0x08048d12 <+70>: mov $0x0,%edx
0x08048d17 <+75>: mov $0x8049960,%ebx
0x08048d1c <+80>: add $0x1,%edx
0x08048d1f <+83>: mov (%ebx,%eax,4),%eax
0x08048d22 <+86>: add %eax,%ecx
0x08048d24 <+88>: cmp $0xf,%eax
0x08048d27 <+91>: jne 0x8048d1c <phase_5+80>
0x08048d29 <+93>: mov %eax,-0xc(%ebp)
0x08048d2c <+96>: cmp $0xb,%edx
0x08048d2f <+99>: jne 0x8048d36 <phase_5+106>
0x08048d31 <+101>: cmp -0x10(%ebp),%ecx
0x08048d34 <+104>: je 0x8048d3b <phase_5+111>
0x08048d36 <+106>: call 0x80492b6 <explode_bomb>
0x08048d3b <+111>: add $0x20,%esp
0x08048d3e <+114>: pop %ebx
0x08048d3f <+115>: pop %esi
0x08048d40 <+116>: pop %ebp
0x08048d41 <+117>: ret
For the line 0x08048d17 <+75>: mov $0x8049960,%ebx
I used
x/16b 0x8049960
gdb and it tells me
0x8049960 array.2954: 10 0 0 0 2 0 0 0
0x8049968 array.2954+8: 14 0 0 0 7 0 00
When I go through the program using until until I get to
0x08048d31 <+101>: cmp -0x10(%ebp),%ecx
%edx = 11, %ecx = 82, and %ebp-0x10 = 2 (used print to get values for first two and x/d $ebp-0x10 for last one)
Because 82 != 2 it just goes to call explode_bomb.
From what I understand it is reading in my 2 numbers, making sure I entered 2 at <+41>.
Then it grabs the first number from the array which in this case is 10 and puts it into $eax at +=<+51>. Then it puts eax into -0xc($ebp) at <+57>.
Then it checks to make sure $eax isn't 15 at <+60>, goes on to set $ecx, and $edx to 0. It then passes the pointer to the array to $ebx at <+75>.
Then it enters a loop from <+80> to <+91> but I am not sure what it is really doing. I get that it increments $edx by 1 and the loop is exited when $eax is 15, but I cant figure out how the rest of the stuff works out.
Am I understanding it correctly up to the loop part? And, if someone wouldn't mind explaining what is happening between <+80> and <+91> I would be very grateful.
p.s. Sorry if my formatting is wrong.

Then it grabs the first number from the array which in this case is
10 and puts it into $eax at +=<+51>.
Wrong. <+51> reads the first number you entered, not the first number from the array. It's then masked into the 0..15 range by discarding the top bits, and is written back to the local variable where it came from. It also lives on in eax, of course.
The array contains 4 byte integers and there are 15 of them. As such you can print it using x/15wd.
Now to the loop. edx is obviously just keeping track of the iteration count, no surprise there. <+83> is the interesting part: it replaces eax with the value of the array item whose index eax currently holds. That is eax = array[eax]. ecx is of course just summing up the array elements you have visited, that's again easy. The exit condition is when you hit the array item that has value 15.
What it all boils down is that this array is really a linked list. The end of the list is marked by a 15. The first number you enter is used as a starting point for list traversal. It should be selected such that you have 11 elements until the end of the list (see <+96>). The second input number should equal the sum of the array items visited.

Related

How to replace a store of EAX with a store of an immediate constant?

From my previous question, I asked how to change the nation code to what I needed it to be. I explored in the disassembly more and I found out exactly where I needed this change to be. In other files, the code seems to be:
mov ds:dword_73A9C8, 1
Where the file I'm trying to edit has it like
mov ds:dword_73A9C8, eax
I've tried to edit the file in IDA by hex to match it to the first line of code, however, the function, even after extending its length, seems to break each time I edit it.
The question I have is how can I change it from having eax being moved to having 1 being moved without breaking the function
sub_4A2B60 proc near
arg_0= dword ptr 4
mov eax, [esp+arg_0]
mov ds:dword_73A9C8, eax
retn
sub_4A2B60 endp
You could replace the 4 byte instruction mov eax, [esp + 4] with the sequence xor eax, eax inc eax nop that also has 4 bytes.
If 1 is what you want, then the return value in EAX should probably also be 1.

Open file, delete zeros, sort it - NASM

I am currently working on some problems and this is the one I am having trouble with. To make it all clear, I am a beginner, so any help is more than welcome.
Problem:
Sort the content of a binary file in descending order. The name of the file is passed as a command line argument. File content is interpreted as four-byte positive integers, where value 0, when found, is not written into the file. The result must be written in the same file that has been read.
The way I understand is that I have to have a binary file. Open it. Get its content. Find all characters while keeping in mind those are positive, four-byte integers, find zeros, get rid of zeros, sort the rest of the numbers.
We are allowed to use glibc, so this was my attempt:
section .data
warning db 'File does not exist!', 10, 0
argument db 'Enter your argument.', 10, 0
mode dd 'r+'
opened db 'File is open. Time to read.', 10, 0
section .bss
content resd 10
counter resb 1
section .text
extern printf, fopen, fgets, fputc
global main
main:
push rbp
mov rbp, rsp
push rsi
push rdi
push rbx
;location of argument's address
push rsi
cmp rdi, 2
je .openfile
mov rdi, argument
mov rax, 0
call printf
jmp .end
.openfile:
pop rbx
;First real argument of command line
mov rdi, [rbx + 8]
mov rsi, mode
mov rax, 0
call fopen
cmp al, 0
je .end
push rax
mov rdi, opened
mov rax, 0
call printf
.readfromfile:
mov rdi, content
mov rsi, 12 ;I wrote 10 numbers in my file
pop rdx
mov rax, 0
call fgets
cmp al, 0
je .end
push rax
mov rsi, tekst
pop rdi
.loop:
lodsd
inc byte[counter]
cmp eax, '0'
jne .loop
;this is the part where I am not sure what to do.
;I am trying to delete the zero with backspace, then use space and
;backspace again - I saw it here somewhere as a solution
mov esi, 0x08
call fputc
mov esi, 0x20
call fputc
mov esi, 0x08
call fputc
cmp eax, 0
je .end
jmp .loop
.end:
pop rdi
pop rsi
pop rbx
mov rsp, rbp
pop rbp
ret
So, my idea was to open the file, find zero, delete it by using backspace and space, then backspace again; Continue until I get to the end of the file, then sort it. As it can be seen I did not attempt to sort the content because I cannot get program to do the first part for me. I have been trying this for couple of days now and everything is getting foggy.
If someone can help me out, I would be very grateful. If there is something similar to this problem, feel free to link it to me. Anything that could help, I am ready to read and learn.
I am also unsure about how much information do I have to give. If something is unclear, please point it out to me.
Thank you
For my own selfish fun, an example of memory area being "collapsed" when dword zero value is detected:
to build in linux with NASM for target ELF64 executable:
nasm -f elf64 so_64b_collapseZeroDword.asm -l so_64b_collapseZeroDword.lst -w+all
ld -b elf64-x86-64 -o so_64b_collapseZeroDword so_64b_collapseZeroDword.o
And for debugger I'm using edb (built from sources) (the executable doesn't do anything observable by user, when it works correctly, it's supposed to be run in debugger single-stepping over instructions and having memory view over the .data segment to see how the values are moved around in memory).
source file so_64b_collapseZeroDword.asm
segment .text
collapseZeroDwords:
; input (custom calling convention, suitable only for calls from assembly):
; rsi - address of first element
; rdx - address beyond last element ("vector::end()" pointer)
; return: rdi - new "beyond last element" address
; modifies: rax, rsi, rdi
; the memory after new end() is not cleared (the zeroes are just thrown away)!
; search for first zero (up till that point the memory content will remain same)
cmp rsi, rdx
jae .noZeroFound ; if the (rsi >= end()), no zero was in the memory
lodsd ; eax = [rsi], rsi += 4
test eax, eax ; check for zero
jne collapseZeroDwords
; first zero found, from here on, the non-zero values will be copied to earlier area
lea rdi, [rsi-4] ; address where the non-zero values should be written
.moveNonZeroValues:
cmp rsi, rdx
jae .wholeArrayCollapsed ; if (rsi >= end()), whole array is collapsed
lodsd ; eax = [rsi], rsi += 4
test eax, eax ; check for zero
jz .moveNonZeroValues ; zero detected, skip the "store" value part
stosd ; [rdi] = eax, rdi += 4 (pointing beyond last element)
jmp .moveNonZeroValues
.noZeroFound:
mov rdi, rdx ; just return the original "end()" pointer
.wholeArrayCollapsed: ; or just return when rdi is already set as new end()
ret
global _start
_start: ; run some hardcoded simple tests, verify in debugger
lea rsi, [test1]
lea rdx, [test1+4*4]
call collapseZeroDwords
cmp rdi, test1+4*4 ; no zero collapsed
lea rsi, [test2]
lea rdx, [test2+4*4]
call collapseZeroDwords
cmp rdi, test2+3*4 ; one zero
lea rsi, [test3]
lea rdx, [test3+4*4]
call collapseZeroDwords
cmp rdi, test3+3*4 ; one zero
lea rsi, [test4]
lea rdx, [test4+4*4]
call collapseZeroDwords
cmp rdi, test4+2*4 ; two zeros
lea rsi, [test5]
lea rdx, [test5+4*4]
call collapseZeroDwords
cmp rdi, test5+2*4 ; two zeros
lea rsi, [test6]
lea rdx, [test6+4*4]
call collapseZeroDwords
cmp rdi, test6+0*4 ; four zeros
; exit back to linux
mov eax, 60
xor edi, edi
syscall
segment .data
; all test arrays are 4 elements long for simplicity
dd 0xCCCCCCCC ; debug canary value to detect any over-read or over-write
test1 dd 71, 72, 73, 74, 0xCCCCCCCC
test2 dd 71, 72, 73, 0, 0xCCCCCCCC
test3 dd 0, 71, 72, 73, 0xCCCCCCCC
test4 dd 0, 71, 0, 72, 0xCCCCCCCC
test5 dd 71, 0, 72, 0, 0xCCCCCCCC
test6 dd 0, 0, 0, 0, 0xCCCCCCCC
I tried to comment it extensively to show what/why/how it is doing, but feel free to ask about any particular part. The code was written with simplicity on mind, so it doesn't use any aggressive performance optimizations (like vectorized search for first zero value, etc).

assembly: sorting numbers using only conditional statments

I am new to assembly and I am trying to write a program that gets five user inputed numbers, stores them in variables num1-num5, sorts them(without using arrays) with num5 having the greatest value and num1 having the lowest value, and then displays the sorted numbers. I am having trouble figuring out how to approach this. I got the 5 numbers and stored them in the variables but I am confused as to how to start with sorting. I have tried a few things but I keep getting errors. This is my code that I can actually get running but it isn't working the way I want it to.
TITLE MASM Template (main.asm)
INCLUDE Irvine32.inc
.data
getnumber byte "Please enter a number between 0 and 20",0ah,0dh,0
num1 byte 0
num2 byte 0
num3 byte 0
num4 byte 0
num5 byte 0
.code
main PROC
call Clrscr
;************* get the information from the user*******************
mov edx, offset getnumber ;ask to input number
call writestring
call readint
mov bl, al
mov num1, bl ;get the number and move to num1 variable
mov edx, offset getnumber ;ask to input number
call writestring
call readint
mov bl, al
mov num2, bl ;get the number and move to num2 variable
mov edx, offset getnumber ;ask to input number
call writestring
call readint
mov bl, al
mov num3, bl ;get the number and move to num3 variable
mov edx, offset getnumber ;ask to input number
call writestring
call readint
mov bl,al
mov num4, bl ;get the number and move to num4 variable
mov edx, offset getnumber ;ask to input number
call writestring
call readint
mov bl, al
mov num5, bl ;get the number and move to num5 variable
;***show the user inputed numbers****
mov al, num1
call writeint
mov al, num2
call writeint
mov al,num3
call writeint
mov al, num4
call writeint
mov al,num5
call writeint
;*****start comparing***
cmp bl,num5
jl jumptoisless
jg jumptoisgreater
jumptoisless:
call writeint
jumptoisgreater:
mov bl, num5
mov dl, num4
mov num5, dl
mov num4, bl
call writeint
jmp imdone
imdone:
call dumpregs
exit
main ENDP
END main
Some notes to your code:
call readint
mov bl, al
mov num2, bl
Why don't you simply store al directly to memory, as: mov [num2],al? You don't use the bl anyway.
Except here:
;*****start comparing***
cmp bl,num5
jl jumptoisless
jg jumptoisgreater
Where I would be afraid what call writeint does to ebx (or you did your homework, and you know from head that call writeint preserves ebx content?).
And if the ebx is preserved, then bl contains still num5 from the input, so it will be equal.
Funnily enough, when equal, you will continue with jumptoisless: part of code, which will output some leftover in al, and then it will continue to jumptoisgreater: part of code, so effectively executing all of them.
Can you watch the CPU for a while in debugger, while single stepping over the instructions, to understand a bit better how it works? It's a state machine, ie. based on the current values in registers, and content of memory, it will change the state of registers and memory in the deterministic way.
So unless you jump away, next instructions is executed after the current one, and jl + jg doesn't cover "equal" state (at least you do cmp only once, so hopefully you understand the jcc instructions don't change flags and both jl/jg operate on the same result of cmp in flags). The Assembler doesn't care about name of your labels, and it will not warn you the "isgreater" code is executed even when "isless" was executed first.
About how to solve your task:
Can't think of anything reasonably short, unless you start to work with num1-num5 memory as array, so you can address it in generic pointer way with index. So I will gladly let you try on your own, just a reminder you need at least n*log_n compares to sort n values, so if you would write very effective sort code, you would need at least 5*3 = 15 cmp instructions (log2(5) = 3, as 23 = 8).
On the other hand an ineffective (but simple to write and understand) bubble sort over array can be done with single cmp inside two loops.
rcgldr made me curious, so I have been trying few things...
With insertion sort it's possible to use only 8x (at most) cmp (I hope the pseudo-syntax is understandable for him):
Insert(0, num1)
// ^ no cmp
Insert((num2 <= [0] ? 0 : 1), num2)
// ^ 1x cmp executed
Insert((num3 <= [0] ? 0 : (num3 <= [1] ? 1 : 2)), num3)
// ^ at most 2 cmp executed
Insert((num4 <= [1] ? (num4 <= [0] ? 0 : 1) : (num4 <= [2] ? 2 : 3)), num4)
// ^ always 2 of 3 cmp executed
Insert((num5 <= [1] ? (num5 <= [0] ? 0 : 1) : (num5 <= [2] ? 2 : (num5 <= [3] ? 3 : 4))), num5)
// ^ at most 3 of 4 cmp executed
=> total at most 8 cmp executed.
Of course doing the "insert" with "position" over fixed variables would be total PITA... ;) So this is half-joke proposal just to see if 8x cmp is enough.
("6 compares" turned out to be my brain-fart, not possible AFAIK)

insertion sort in assembly does not work

I have tried to write an insertion sort in assembly (nasm), and it doesn't work (always sent segmentation fault).
I tried to search the source of the problem for really long time and I cannot find it,
can someone please help me to find the problem?
thank you.
sort:
pushad
mov ebp,esp;creating stack frame
mov ebx,[ebp+36]; ebx saves pointer to the array
mov ecx,[ebp+40];ecx saves the srray size
mov esi,4 ; i
for_l1:
;edx=temp,esi=i,edi=j
mov edx,[ebx+esi]
mov edi,esi;j=i
sub edi,4;j=i-1
while_l1:
cmp edx,[ebx+edi]; if(temp<array[j])
jge end_while1
;array[j+1]=array[j], j-=1
mov eax,[ebx+edi]
mov [ebx+edi+4],eax
sub edi,4
cmp edi,0
jge while_l1;if(j>=0)
end_while1:
;array[j+1]=temp
mov[ebx+edi+4],edx
add esi,4;i+=1
dec ecx; decreasing the size of the array needed to sort
cmp ecx,1;if(size==1)
jg for_l1
finished1:
popad
ret 8
Are you sure array size represents the number of elements and that it doesn't contain the total length of the array?
Then perhaps you could code
mov ecx,[ebp+40];ecx saves the srray size
shr ecx,2

Insertion sort in Assembly

So I'm coding out an insertion sort (in assembly) based on this high level code:
void insertionSort(int data[ ], int arraySize) {
int insert;
int moveItem;
for(int next=1; next<arraySize; next++) {
insert=data[next]; //store the value in the current element
moveItem=next; //initialize location to place element
while((moveItem>0)&&(data[moveItem-1]>insert)) {
//shift element one slot to the right
data[moveItem]=data[moveItem-1];
moveItem--;
} //end while
data[moveItem]=insert;
} //end for
} //end insertionSort
There are exactly 20 random numbers in an array called myArray. I cannot use an of the decision derivatives that come in the library that comes with our book. So basically movs, cmps, loops, and jumps
Here's what I got. I had it sorting the first of 20 random numbers earlier, but I've confused myself to death and have no idea what I'm doing any more. It crashes when it gets to the insertion sort method. Help please.
TITLE Insertion Sort (main.asm)
INCLUDE Irvine32.inc
.data
elems = 20
myArray sdword elems dup(0)
str1 byte "Press enter" ,0
str2 byte "The array now is ",0
next sdword 1
start sdword ?
.code
main PROC
call Clrscr
call CreateRandom
call Display
call InsertionSort
call Display
exit
main ENDP
CreateRandom PROC
;;;;Creates 20 random numbers and populates myArray;;;;;
call Randomize
mov ecx, 20
mov edx, OFFSET myArray
L1:
call Random32 ;create random number
mov [edx], eax ; move random number to the appropriate spot in the array
add edx, 4 ; increase the address of what it is pointing to
loop L1
mov edx, OFFSET str1 ; "press enter to continue"
call WriteString
call ReadInt
call Crlf
ret
CreateRandom ENDP
Display PROC
;;;; Displays current form of the array myArray;;;;;
mov edx, OFFSET str2 ; "The array now is:"
call WriteString ; write string
call Crlf
mov esi, OFFSET myArray ; offset of the array
mov ecx, 20 ; index of the loop
L2:
mov eax, [esi] ; move array at that point to eax
call WriteDec ; print out the array as a decimal
call Crlf ; next line
add esi, 4 ; next element in the array
loop L2
call Crlf
ret
Display ENDP
InsertionSort PROC
mov ecx, 19
mov edx, OFFSET myArray
mov ebx, OFFSET myArray ; eax=next
add ebx, 4 ;moves up the array to second element comparable to next
outterloop:
mov esi, [ebx] ; esi=data[next]
mov eax, ebx ;movelterm=ebx
L1:
mov edx, [eax-4] ;move the number that is greater into edx
mov [eax], edx ;move the number into that 2nd element of the
sub eax, 4
mov esi, [eax]
cmp eax, [edx]
JNG endinner ; if the address is not greater than the first address, skip to the end
mov edx, [eax-4]
cmp edx, esi ; if the address is greater, than it already sorted, skip to end
JG endinner
loop L1
endinner:
mov [eax], esi ; move first to the second to finish the sort
add ebx, 4 ;move to the next element of the array
inc next ;counting outside loop
cmp ecx, next
JNE outterloop ;return to top of for loop
ret
InsertionSort ENDP
END main
I haven't examined your code in detail, but I notice that InsertionSort seems to be using edx for two different purposes at once: as a pointer into the array, and to hold one of the values from the array. This will certainly break even if nothing else is wrong.
So, at the start of InsertionSort you say mov edx, OFFSET myArray -- it's a pointer into the array. Then, a few lines later, mov edx, [eax-4] -- oops, no, it's a value from the array. And a few lines later again, cmp eax, [edx] -- oh, no, now it's a pointer into the array again.
Perhaps that last instruction should be cmp edx, [eax] or something? Because eax does seem to be a pointer into the array here.

Resources