Building a Specific Pattern
The following is the algorithm used to build the pattern.
We will use a pattern consisting of 8 by 7 bits saved as data
Set initial display address in RD
Repeat 7 times: (number of rows in the pattern)
Load RA with RD
Repeat while address in RA is < FF:
Repeat 4 times: (number of times that a pattern fits in a display row)
Load the current byte of the pattern
Save in current display address
Increment display address
Increment display address in RA by 24 to go to the next repeated row
Increment RD to advance to next display row
Increment current byte of pattern to get the next pattern row
The algorithm solves the problem by printing every row in the pattern repeatedly, 4 times in a display row, and then until we reach the end of the display, incrementing by the pattern height times display row size each time.
After the program is assembled and load, we proceed to run it. The run goes step by step through the code, first loading the registers with the initial values and then going through the nested loops.
The registers that change value very rapidly are R0, R3, and RA the registers R5, RC, and RD change slowly and every other register doesn’t change when the program is in the loops.
The screenshot shows the program after running
When the program ends running the bitmap display has the following pattern in it:
We were able to make the same pattern that was required so the program ran as expected.
The number of instructions executed was 948.
The program uses registers R1, RF, R4, R8, R6, and R7 to hold constant values. The following table shows the values of those constant registers:
R1 and RF are used to increment and decrement counters, respectively. R4 is used to count the number of patterns per display row, which is 4 since the patterns are 8 bits of width and the display has 32 bits per row. R8 is the separation between repeated patterns in different display rows since the patterns are 7 rows of height and each row in the display has 4 patterns, then the next pattern repetition is at 4*7 =28 bytes below since we need to go to the next repeated row after we have displayed a row of 4 patterns, then we only need to increment 28-4=24 to go to the next repeated row, since 24 is 18 in hexadecimal, that is the value we put in R8. The values in R6 and R7 are necessary to use the JMPNE and JMPGT instructions, which require the jump address to be saved in a register.
The program goes through three nested loops to print the pattern. The outer loop is for printing each row in the pattern, since the pattern has 7 rows, we have to loop 7 times, the counter for this loop is RC, and we initialize it to 7, we keep track of the current row pattern in R5 that has the address of the current row in the pattern. At the start, R5 is loaded with the address of the pattern. After all the processing is done for the RC loop, we increase the pattern row, which is held in R5 and we decrement RC, if it’s not zero we repeat the cycle, otherwise, we end the program.
The following loop is nested inside the RC loop. This next loop is used to go through repeated rows in the display. The counter for this loop is the register RA, which initially is loaded with the start display address. After all the processing within the loop is completed, the value of RA is incremented by 24 to go to the next repeated row, if after incrementing RA we wrap around, that is, we end with a value lower than 24, then we end the RA loop and continue with updating the variables of the outer RC loop.
The innermost loop is the one that prints 4 times the current pattern in a display row. The counter for this loop is held in R3. Inside the loop, R0 is loaded with the current pattern row, which is at the address given in R5, then the pattern is copied to the current display address, which is in RA, then the display address is incremented by one to point to the next display position and the loop counter is decremented by one if the counter is not zero the process repeats to print all 4 patterns in a row. Otherwise, it ends the R3 loop and continues with the updating of the RA loop.
a) What is a disassembler? How could a security analyst use a disassembler to investigate computer malware? What are the limitations of a disassembler for this task?
A disassemble is a program that takes an object file, which in most cases corresponds to an executable file for a program, and translates the machine code saved in it to assembly code. In other words, a disassemble makes the inverse process done by an assembler, it takes machine code written for a specific machine and translates it to assembly code. In most cases, this process is quite straightforward since every machine code corresponds exactly to a single assembly code representation.
The disassembly process has several uses, one of them is determining if a given executable file contains malicious code that could harm the normal computer processing or could lead to a security breach. Such malicious programs are part of the so-called malware. However, in most cases, the resulting assembly code is too complex to be analyzed directly. The disassembled code could contain hundreds of thousands of instructions and analyzing it directly could be quite difficult. In most instances, the malware search looks for instructions that change the execution level of the program, allowing it to have privileged access to a computer or for instructions that modify files in the system. A set of suspicious instructions can be disassembled and run in a different system; to determine the actual effect of the malicious code and also for providing a signature for the malware being analyzed that could result in a fix for it, by searching for the set of instructions that belong to it in every other file.
There are some instances in which being the machine code inside a malware-infected file cannot be used to generate assembly code, for example, when the binary contents have been preprocessed in some way to avoid being read directly, perhaps by using encryption tools or by using invalid instructions, which can confuse the disassemble and lead to incorrect assembly code, resulting in code that doesn't correspond to the malware.
b) What is an interpreter? Why do some programming environments contain both an interpreter and a compiler for the same language?
An interpreter is a program that takes a file written in some high-level language and executes the instructions in it line by line without generating actual machine code for it. In most cases, the execution of a program in an interpreter is slower than the execution of a similar compiled program. This is because of the overhead introduced by analyzing the current line and generating the series of low-level instructions that correspond to it and also because loops imply that multiple instructions must be reinterpreted several times.
In some cases, a given programming language can have both a compiler and an interpreter. This can help develop applications since the interpreter can be used to debug parts of the program being written, and can thus speed up the program development since compiling a huge application to test parts of it can be a slow process. The compiler can then be the last step on the program development and the generated machine code can be fully optimized to take advantage of the host machine capabilities. In some other cases the compilation process is internal, that is, the interpreter uses internally a virtual machine code representation of the program. This virtual machine code is generated by a compiler. The machine code for this kind of interpreters is intermediate, not being machine code for the host computer, but an internal representation that can speed the execution of the program and provide binary code compatibility between different platforms.