Hi Everyone,

In this blog, we will complete the remaining instructions. Honestly, I was going to put all the instructions in one single blog. But during course of writing that blog, I started getting bored and tired. I realized that most of you guys will start feeling same. Hence, I abruptly stopped there and decided to split one big blog into two smaller blogs. So let’s start part 2 of Important instructions.

String Instructions:

String in assembly language is an array of bytes or words. Generally, operations available for String are

  1. Copy one string into another
  2. Search a partial string in one string
  3. Store characters in a string
  4. compare two strings

and this may go on……
Before starting with string instructions, we must know about related registers and flags.

  • Source DS:SI, Destination ES:DI
  • You must ensure DS and ES are correct
  • You must ensure SI (Source Index) and DI (Destination Index) are offsets into DS and ES respectively
  • Direction Flag (0 = Up, 1 = Down)
  • CLD  – Increment addresses (left to right)
  • STD – Decrement addresses (right to left)

The Direction Flag

  • One of the control flags in the FLAGS register is the direction flag (DF)
  • It determines the direction in which string operations will proceed
  • The string operations are implemented by the two index registers SI and DI
  • If DF = 0, SI and DI proceed in the direction of increasing memory addresses
  • If DF = 1, they proceed in decreasing direction

CLD and STD

  • To make DF = 0, use the cld instruction

cld     ; clear direction flag

  • To make DF = 1, use the std instruction

std     ; set direction flag

  • cld and std have no effect on the other flags

Now that we know about these two important flags, let’s start looking into some important instructions related to string operation.

Instruction for moving the strings: Suppose you have two strings with you. STR1 and STR2. STR1 is initialized string, while STR2 is uninitialized string. MOVS(B/W/D) will help you to move content from STR1 to STR2. Here B=Byte, W=Word, D= Double Word. It copies content of B/W/D addressed by DS:SI to B/W/D address by ES:DI. Below is the sample code

You can see that, writing MOVS* every time is kinda pain. In this case, REP comes to rescue. You just need to initialize CX register, append rep before MOVS* and bam!!! You are done. Example:

Instruction for storing a string: Suppose you have to store data from Register to String. STOS* will help you. Moves the contents of the AL register to the byte addressed by ES:DI. DI is incremented if DF=0 or decremented if DF=1

It has following variants.

  • STOSB (Store data from AL to ES: (E)DI)
  • STOSW (Store data from AX to ES: (E)DI)
  • STOSD (Store data from EAX to ES: (E)DI)

Example:

Here also you can use REP prefix.

Instruction for loading string from memory: To load string from Memory to register. LODS* will help you. Moves the byte addressed by DS:SI into the AL register. SI is incremented if DF=0 or decremented if DF=1.

It has following variants.

  • LODSB (Load data from DS:(E)SI into AL)
  • LODSW (Load data from DS:(E)SI into AX)
  • LODSB (Load data from DS:(E)SI into EAX)

Example:

Instruction to scan a string: Suppose you want to check if particular sequence is present or not. SCAS* will help you. It examines a string for a target byte (contained in al). subtracts the string byte pointed to by ES:EDI from AL/AX/EAX (for B/W/D respectively) and sets the flags (OF, SF, ZF, AF, PF, and CF) . the result is not stored. di is incremented if DF = 0 or decremented if DF = 1.

Example:

Now generally we need conditional statements for these kinds of operation. Think about For loop. It stops when some condition is met. We can achieve same thing with variants of REP i.e. REPNE (Repeat while not equal; occurs when ZF=1 or CX=0), REPE (Repeat while Equal; occurs when ZF=0 or CX=0).

Example:

Instruction to compare strings: Do you want to compare length of two strings? CMPS* will be the helpful. subtracts the byte addressed by DS:SI from the byte addressed by ES:DI, sets the flags, and throws the result away afterward, both SI and DI are incremented if DF=0; if DF=1, they are decremented. All status flags are affected by cmpsb and cmpsw.

Since we have looked into important instructions, finally we can move towards real code to check how they actually works. Then let’s begin…….

Note: I’ll be showing only one example of each instruction. You can rest of examples on your own. You know its very hectic to write, debug + take so many screenshots. 😛 Cannot help.

Now then, below is the code for above string operations.

As you can see there are multiple iterations of some code. That is probably because I’m keeping things clean. That is very important thing you’ll learn when you have to write shellcodes etc. But that is not relevant right now.

Now we will start debugging with our beloved GDB with PEDA.

First 3 instructions are register cleanup. You’ll find them again and again in code. So ignore them.
MOVSB Instruction:

In this screenshot you can observe that ECX, ESI, EDI are loaded and DF = 0. Hence we can start REP MOVSB operation. It will repeat till ECX = 0.

Let skip couple steps to observe effect of MOVSB in next screenshot.

As you can see, Characters moved from Source to destination string.

STOSB Instruction:

In Storage instructions, we will take character from register and store it in destination string. For that, we have Moved ‘A’ in EAX, Loaded EDI with destination string. For this particular occasion I’m not making any changed to DF.

Now just like last time, let’s skip couple of steps to see effect of STOSB instruction.

As you can see, after two iterations, AA stored in destination string.

LODSB Instruction:

Now we will see LODSB instruction which will load string to register byte by byte. For that, we have loaded source index of string in ESI.

Lets see the effect of LODSB after execution.

As we can see ‘b’ is moved in EAX.
SCASB Instruction:

In this we will be byte by byte scanning of target string for character loaded in EAX. We can see we have opted for both conditions. For Match EDX=1 and Not Match EDX=2. Initially we have loaded EDI with target string, updated ECX for REP instruction and loaded EAX with ‘d’, which we know that present in string.

You can observe that our code worked. You can also observe that each byte after scanning is scraped out of EDI. This happens because of something call page address alignment. We will look into that in detail while writing Egg Hunter code.

Similar thing will happen with not match condition. Feel free to try.
CMPSB Instruction:

This is different than SCANNING. In this we load two strings in ESI and EDI. Result will be 0 for match and 1 for match. In this we have loaded ECX=5 for REP, ESI, EDI. We have written equality check and print routine to see if those strings match.

As we know, strings do not match.

With this we have successfully (skipped) completed string instructions. Please check rest of them yourself. It’s very necessary. 😛

Logical Operations:

In this final section, we will be looking into Logical operation available in x86 Linux assembly language. So that this post will be very long. (Evil Laugh…..) When we talk about logical instructions, they are something like binary operations we have learned in school.  I know this is very lame statement, but that’s what I can recall. So, bear with it.

In x86 (rather any binary based architecture) most common logical instructions are AND, OR, NOT, XOR etc. As you already know how these instructions works, I’m skipping the explanation.

.
.
.
.
.
.
.
.
.
.
Ok ok… let me explain in very short manner.

AND Instruction: In AND gate, you’ll get HIGH (1) output only and only if all inputs are HIGH. Refer below table:

In assembly, and is the equivalent instruction. Its format is AND operand1, operand2. It stores result in first operand. Example:

NOT Instruction: In NOT gate, output will be inverse of input.

In assembly, not is the equivalent instruction. Its format is NOT operand1. This will flip the state of all bit values in operand. Example:

OR Instruction: In OR gate, output will be high if any one of the inputs is high.

In assembly, or is equivalent instruction. Its format is OR operand1, operand2. It stores result in first operand.

XOR Instruction: In eXclusive OR gate, for two different inputs, output will be HIGH.

In assembly, xor is the equivalent instruction. Its syntax is XOR operand1, Operand2. It stores result in first operand. (Note: If you have not forgot my last code, you might have seen many XOR operations over there. Now you can see why I used them there. :P). Example:

Now it’s time for coding…..

So above is the code. After assembling and linking, let’s start with debugging the code to observe the functioning of instructions.

After initial clean-up instructions, we are ready to start debugging.

First is AND instruction. First we will move 5 in EAX. Then 6 in EBX. When AND operation performed, it will happen this way.

(5)h = (0101)b , (6)h = (0110)b. Result of AND operation will be (0100)b which is (4)h. This value will be stored in EAX. Hence after couple of steps, EAX = 4.

Next is NOT instruction. For this we are using ECX register. We will load (A)h in EAX. Now (A)h = (1010)b. NOT will flip all bits. Hence output will be (0101)h = (5)h. This will be stored in CL. Value of ECX will be (fffffff5)h.

Next up is OR instruction. For this, we will load (7)h = (0111)b in EAX, and (8)h = (1000)b in EBX. Result of OR will be (1111)b = (f)h. It will be stored in EAX.

Finally we will execute XOR. In this we will load (A)h = (1010)b in EAX and (B)h = (1011)b in EBX. Its result will be (0001)b = (1)h. This will be stored in EAX.

With this, I’m concluding the blogpost. I know I have not considered many instructions. But during writing this blog post, I realized that they are better to be checked during their actual usage while doing shellcoding.

In next post, we will look at how to use assembly language code in C program. Since it’s not convenient to write everything in assembly, we have to use C sometime. Till then Auf Wiedersehen!!!!!

Leave a Reply