banner
lca

lca

真正的不自由,是在自己的心中设下牢笼。

"Learning Notes on Starting from Zero to Learn IDA Reverse Engineering - 4 (Stack Learning)"

XCHG

xchg  A,B #Instruction used to swap the values of A and B

Place the mouse over 0x4013d8, there is an xor eax,eax instruction here. This demonstrates modifying the instruction at address 0x4013d8. Click on the menu bar Edit-Patch program-Assemble.

A window will pop up as shown below.
Enter the instruction that needs to be modified, and it will be modified.

xchg eax,esi

After writing the new instruction, the original function is interrupted.

Change 0xc0 to NOP, the NOP (NO OPERATION) instruction does nothing, it has no operation. The modified content is as follows:

In the above example, only one byte is involved, the original data type is db, with a value of 0xc0h.

However, after the modification, the function is interrupted at this time, and you can right-click on the starting address of the function 0x4013d8 and select Create function.

After the function is created, the content is as follows:

IDA changes the previous loc_ (representing normal instructions) to sub_ (representing the start of the function). Now it has been re-recognized as a function, press the space bar to switch to the graph view.

Re-focus on the XCHG instruction here. Assuming EAX = 12345678, ESI = 55, after the instruction is executed, EAX becomes 55 and ESI becomes 12345678.

There is a PATCHED BYTES function in the PATCH menu, which can display all modified bytes and also cancel the modifications.

The XCHG instruction can also swap the value of a register with the value stored in memory pointed to by another register.

For example: xchg eax, [esi]

If eax = 55 and esi = 0x10000, the program will look up the value stored at 0x10000. If the address has write permission, it will store 55 and the original value at 0x10000 will be written into eax.

4.3 Stack Operation Instructions

The Stack is a temporary memory area occupied by the function during operation. The memory access mode is First In Last Out (FILO), which stores and retrieves data in this way.

The characteristic of the stack is that the frame that enters the stack last is the first to exit the stack (because the innermost function call ends first), which is called a Last In First Out data structure.

There are two basic operations for data manipulation on the stack:

  • PUSH: Saves an object at the top of the stack (pushes it onto the stack).

  • POP: Retrieves the object most recently stored at the top of the stack.

  • At any time, only the top of the stack or the most recently pushed object can be operated on.

The POP operation retrieves the object most recently stored at the top of the stack, and then the object below it (stored by the second-to-last push operation) becomes the object stored by the last push operation, allowing for subsequent operations.

The stack is allocated starting from the end address of the memory area, and is allocated from the high-order (address) to the low-order (address). For example, if the end address of the memory area is 0x00001000, assuming the first frame is 4 bytes, the next allocation will start from 0x00000FFC, as shown in the above figure.

push

In 32-bit programs, PUSH is usually used to pass parameters to the stack before calling a function, for example, in the instruction at 0x40104f in the above figure. The PUSH 64 instruction pushes 64 (dword) onto the top of the stack, and PUSH EAX pushes the value of EAX onto the stack, stored above the previous 64 (dword), and now the value of EAX is at the top of the stack.

PUSH can operate on different objects, in addition to constants, it can also operate on addresses.

The OFFSET keyword can be seen in front of the string name, and this instruction will push the address of this string or character array onto the stack.

Double-click on the string name to jump to the following figure.

In general C language source code, character arrays are defined as follows: Char mystring[] = "Hello"

Press the D key to change the data type of windowname, forcing IDA to treat it as a byte or db.

After modification, some instructions that reference this address will change accordingly. In the figure below, the offset keyword ensures that the address passed in is still 0x004020e7, but what is stored at the address is no longer a character array, but a byte.

The entire instruction becomes push offset byte_4020E7, and the content of byte_4020E7 is changed to the db type.

In the above example, only one byte is involved, the original data type is db, with a value of 0xc0h.

However, after the modification, the function is interrupted at this time, and you can right-click on the starting address of the function 0x4013d8 and select Create function.

After the function is created, the content is as follows:

IDA changes the previous loc_ (representing normal instructions) to sub_ (representing the start of the function). Now it has been re-recognized as a function, press the space bar to switch to the graph view.

Re-focus on the XCHG instruction here. Assuming EAX = 12345678, ESI = 55, after the instruction is executed, EAX becomes 55 and ESI becomes 12345678.

There is a PATCHED BYTES function in the PATCH menu, which can display all modified bytes and also cancel the modifications.

The XCHG instruction can also swap the value of a register with the value stored in memory pointed to by another register.

For example: xchg eax, [esi]

If eax = 55 and esi = 0x10000, the program will look up the value stored at 0x10000. If the address has write permission, it will store 55 and the original value at 0x10000 will be written into eax.

4.3 Stack Operation Instructions

The Stack is a temporary memory area occupied by the function during operation. The memory access mode is First In Last Out (FILO), which stores and retrieves data in this way.

The characteristic of the stack is that the frame that enters the stack last is the first to exit the stack (because the innermost function call ends first), which is called a Last In First Out data structure.

There are two basic operations for data manipulation on the stack:

  • PUSH: Saves an object at the top of the stack (pushes it onto the stack).

  • POP: Retrieves the object most recently stored at the top of the stack.

  • At any time, only the top of the stack or the most recently pushed object can be operated on.

The POP operation retrieves the object most recently stored at the top of the stack, and then the object below it (stored by the second-to-last push operation) becomes the object stored by the last push operation, allowing for subsequent operations.

The stack is allocated starting from the end address of the memory area, and is allocated from the high-order (address) to the low-order (address). For example, if the end address of the memory area is 0x00001000, assuming the first frame is 4 bytes, the next allocation will start from 0x00000FFC, as shown in the above figure.

push

In 32-bit programs, PUSH is usually used to pass parameters to the stack before calling a function, for example, in the instruction at 0x40104f in the above figure. The PUSH 64 instruction pushes 64 (dword) onto the top of the stack, and PUSH EAX pushes the value of EAX onto the stack, stored above the previous 64 (dword), and now the value of EAX is at the top of the stack.

PUSH can operate on different objects, in addition to constants, it can also operate on addresses.

The OFFSET keyword can be seen in front of the string name, and this instruction will push the address of this string or character array onto the stack.

Double-click on the string name to jump to the following figure.

In general C language source code, character arrays are defined as follows: Char mystring[] = "Hello"

Press the D key to change the data type of windowname, forcing IDA to treat it as a byte or db.

After modification, some instructions that reference this address will change accordingly. In the figure below, the offset keyword ensures that the address passed in is still 0x004020e7, but what is stored at the address is no longer a character array, but a byte.

The entire instruction becomes push offset byte_4020E7, and the content of byte_4020E7 is changed to the db type.

Press the A key to convert it to an ASCII string, restoring it to its initial display.

When other strings are displayed as individual bytes, this operation can also be performed. Find the starting point of the string and press the A key to make the display more readable.

For example:

Press the X key to find the references to the string.

In general, when passing parameters to a function, the PUSH offset xxxxx instruction is usually used to pass the address of the string to the function. If there is no offset keyword, what is passed in is the content stored at address 0x402110, which is the specific bytes of the string 55 4E 45 4D. However, API functions do not work like this, they generally accept a pointer or the starting address of the string as a parameter.

In the above instructions, the DS: label indicates that the program will write on the memory in the data block (DS=DATA).

pop instruction

The POP instruction reads the value at the top of the stack and transfers it to the destination register. As shown in the figure below, POP EDI reads the first value at the top of the stack and passes it to the EDI register, and sets the value of ESP to the value below the one that was read, making it the top of the stack.

By searching for pop in the text, it can be seen that the usage of the pop instruction has not changed much, and the value is not popped into an address.

Reference: Assembly Language Primer - Ruanyifeng's Blog

Loading...
Ownership of this post data is guaranteed by blockchain and smart contracts to the creator alone.