Hi Guys

One more time, am trying to understand the opcode and operands here and how the conversion is done....

For example consider this,

CALL 004010D6

The equivalent opcode for the above is "E8 67000000".

Please tell me how did 004010D6 was converted to 67000000? I understand the opcode for the CALL instruction is E8. But unsure how the address was converted  ;)

Any help is much appreciated!
Posted on 2009-07-21 09:04:46 by karthikeyanck
Relative address?
Posted on 2009-07-21 10:35:50 by ti_mo_n

Relative address?


Yep. CALL can be (and usually is) 32-bit relative (+/- 2GB).
Posted on 2009-07-21 10:38:48 by SpooK


Relative address?


Yep. CALL can be (and usually is) 32-bit relative (+/- 2GB).


Oh yeah, those are from Olly.... any idea on how to achieve this?
Posted on 2009-07-21 10:50:29 by karthikeyanck
Add manually?

The opcode means the following (Olly helped you do the addition):


curr: call curr+67h
Posted on 2009-07-21 11:41:09 by roticv
Say if I'm calling the function MessageBoxA; will the address of the function remain the same always?

I don't think that is the case, I get the address of the function using LoadLibrary and GetProcAddress....

The goal here is to display a messagebox, I've managed to push the opcode...

mov DWORD PTR,0E8h           ;opcode for call


Am fine till I push the opcode for CALL, but then I've the address of the MessageBox function in the edx (004010DA).... how would I pass this on as opcode?

Sorry but I didn't understand this - I believe you are saying to add 67 to the address shown in Olly?

Add manually?

The opcode means the following (Olly helped you do the addition):

Code:

curr: call curr+67h


Thanks,

C K
Posted on 2009-07-22 02:40:02 by karthikeyanck
I think you do not understand the opcode encoding and what the rest meant by call by relative address. E8h is call by relative address, ie suppose the call is done at 100h  and you call +10h, it means you are calling the address 110h.

The address will differ from machines to machine, but I do not think it will change that much for the same system.

Suppose you have the address you want to call is in eax, then you can do call .

PS: The svin has some good tutorials on opcode encoding on this forum - search for opcode.
Posted on 2009-07-22 10:16:48 by roticv
I can't seem to get a solution even after reading the SVIN tuts....
I could only manage to push the Address of the MessageBox function.. meaning the address is hard coded..

mov DWORD PTR, 07e04f4d6h              ;pushing the address for the messagebox function


Am sure this isn't the right way to do this, but neverthelesss this works!... but I fear this will break if the function is loaded to a different location in the memory?  :sad:

Any suggestions?
Posted on 2009-07-28 10:24:59 by karthikeyanck
Change the import table so that you have an addition entry for MessageBoxA. call that address like how like jump table in masm generated code works.
Posted on 2009-07-28 10:36:08 by roticv
destination_address = getprocaddress(mbox)

start_address:
db 0E8h
dd destination_address-return_adress
return_adress:
Posted on 2009-07-28 15:39:28 by drizz
Drizz, Wonderful, thanks for that, works perfectly  :D
Posted on 2009-07-29 09:55:26 by karthikeyanck
This may be helpful to you...

Intel® 64 and IA-32 Architectures Software Developer's Manual
Volume 1: Basic Architecture:
6.3.1 Near CALL and RET Operation
When executing a near call, the processor does the following (see Figure 6-2):
1. Pushes the current value of the EIP register on the stack.
2. Loads the offset of the called procedure in the EIP register.
3. Begins execution of the called procedure.
When executing a near return, the processor performs these actions:
1. Pops the top-of-stack value (the return instruction pointer) into the EIP register.
2. If the RET instruction has an optional n argument, increments the stack pointer
by the number of bytes specified with the n operand to release parameters from
the stack.
3. Resumes execution of the calling procedure.

6.3.2 Far CALL and RET Operation
When executing a far call, the processor performs these actions (see Figure 6-2):
1. Pushes the current value of the CS register on the stack.
2. Pushes the current value of the EIP register on the stack.
3. Loads the segment selector of the segment that contains the called procedure in
the CS register.
4. Loads the offset of the called procedure in the EIP register.
5. Begins execution of the called procedure.
When executing a far return, the processor does the following:
1. Pops the top-of-stack value (the return instruction pointer) into the EIP register.
2. Pops the top-of-stack value (the segment selector for the code segment being
returned to) into the CS register.
3. If the RET instruction has an optional n argument, increments the stack pointer
by the number of bytes specified with the n operand to release parameters from
the stack.
4. Resumes execution of the calling procedure.


Intel® 64 and IA-32 Architectures Software Developer's Manual
Volume 2A: Instruction Set Reference, A-M:
Near Call. When executing a near call, the processor pushes the value of the EIP
register (which contains the offset of the instruction following the CALL instruction)
on the stack (for use later as a return-instruction pointer). The processor then
branches to the address in the current code segment specified by the target operand.
The target operand specifies either an absolute offset in the code segment (an offset
from the base of the code segment) or a relative offset (a signed displacement relative
to the current value of the instruction pointer in the EIP register; this value
points to the instruction following the CALL instruction). The CS register is not
changed on near calls.
For a near call absolute, an absolute offset is specified indirectly in a general-purpose
register or a memory location (r/m16, r/m32, or r/m64). The operand-size attribute
determines the size of the target operand (16, 32 or 64 bits). When in 64-bit mode,
the operand size for near call (and all near branches) is forced to 64-bits. Absolute
offsets are loaded directly into the EIP(RIP) register. If the operand size attribute is
16, the upper two bytes of the EIP register are cleared, resulting in a maximum
instruction pointer size of 16 bits. When accessing an absolute offset indirectly using
the stack pointer as the base register, the base value used is the value of the
ESP before the instruction executes.
A relative offset (rel16 or rel32) is generally specified as a label in assembly code. But
at the machine code level, it is encoded as a signed, 16- or 32-bit immediate value.
This value is added to the value in the EIP(RIP) register. In 64-bit mode the relative
offset is always a 32-bit immediate value which is sign extended to 64-bits before it
is added to the value in the RIP register for the target calculation. As with absolute
offsets, the operand-size attribute determines the size of the target operand (16, 32,or 64 bits). In 64-bit mode the target operand will always be 64-bits because the
operand size is forced to 64-bits for near branches.

Far Calls in Protected Mode. When the processor is operating in protected mode, the
CALL instruction can be used to perform the following types of far calls:
• Far call to the same privilege level
• Far call to a different privilege level (inter-privilege level call)
• Task switch (far call to another task)
In protected mode, the processor always uses the segment selector part of the far
address to access the corresponding descriptor in the GDT or LDT. The descriptor
type (code segment, call gate, task gate, or TSS) and access rights determine the
type of call operation to be performed.
If the selected descriptor is for a code segment, a far call to a code segment at the
same privilege level is performed. (If the selected code segment is at a different privilege
level and the code segment is non-conforming, a general-protection exception
is generated.) A far call to the same privilege level in protected mode is very similar
to one carried out in real-address or virtual-8086 mode. The target operand specifies
an absolute far address either directly with a pointer (ptr16:16 or ptr16:32) or indirectly
with a memory location (m16:16 or m16:32). The operand- size attribute
determines the size of the offset (16 or 32 bits) in the far address. The new code
segment selector and its descriptor are loaded into CS register; the offset from the
instruction is loaded into the EIP register.
A call gate (described in the next paragraph) can also be used to perform a far call to
a code segment at the same privilege level. Using this mechanism provides an extra
level of indirection and is the preferred method of making calls between 16-bit and
32-bit code segments.
When executing an inter-privilege-level far call, the code segment for the procedure
being called must be accessed through a call gate. The segment selector specified by
the target operand identifies the call gate. The target operand can specify the call
gate segment selector either directly with a pointer (ptr16:16 or ptr16:32) or indirectly
with a memory location (m16:16 or m16:32). The processor obtains thesegment selector for the new code segment and the new instruction pointer (offset)
from the call gate descriptor. (The offset from the target operand is ignored when a
call gate is used.)
On inter-privilege-level calls, the processor switches to the stack for the privilege
level of the called procedure. The segment selector for the new stack segment is
specified in the TSS for the currently running task. The branch to the new code
segment occurs after the stack switch. (Note that when using a call gate to perform
a far call to a segment at the same privilege level, no stack switch occurs.) On the
new stack, the processor pushes the segment selector and stack pointer for the
calling procedure’s stack, an optional set of parameters from the calling procedures
stack, and the segment selector and instruction pointer for the calling procedure’s
code segment. (A value in the call gate descriptor determines how many parameters
to copy to the new stack.) Finally, the processor branches to the address of the
procedure being called within the new code segment.
Executing a task switch with the CALL instruction is similar to executing a call
through a call gate. The target operand specifies the segment selector of the task
gate for the new task activated by the switch (the offset in the target operand is
ignored). The task gate in turn points to the TSS for the new task, which contains the
segment selectors for the task’s code and stack segments. Note that the TSS also
contains the EIP value for the next instruction that was to be executed before the
calling task was suspended. This instruction pointer value is loaded into the EIP
register to re-start the calling task.
The CALL instruction can also specify the segment selector of the TSS directly, which
eliminates the indirection of the task gate. See Chapter 7, “Task Management,” in the
Intel® 64 and IA-32 Architectures Software Developer’s Manual, Volume 3A, for
information on the mechanics of a task switch.
When you execute at task switch with a CALL instruction, the nested task flag (NT) is
set in the EFLAGS register and the new TSS’s previous task link field is loaded with
the old task’s TSS selector. Code is expected to suspend this nested task by executing
an IRET instruction which, because the NT flag is set, automatically uses the previous
task link to return to the calling task. (See “Task Linking” in Chapter 7 of the Intel®
64 and IA-32 Architectures Software Developer’s Manual, Volume 3A, for information
on nested tasks.) Switching tasks with the CALL instruction differs in this regard from
JMP instruction. JMP does not set the NT flag and therefore does not expect an IRET
instruction to suspend the task.

IF far call and (PE = 1 and VM = 0) (* Protected mode or IA-32e Mode, not virtual-8086 mode*)
THEN
IF segment selector in target operand NULL
THEN #GP(0); FI;
IF segment selector index not within descriptor table limits
THEN #GP(new code segment selector); FI;
Read type and access rights of selected segment descriptor;
IF IA32_EFER.LMA = 0
THEN
IF segment type is not a conforming or nonconforming code segment, call
gate, task gate, or TSS
THEN #GP(segment selector); FI;
ELSE
IF segment type is not a conforming or nonconforming code segment or
64-bit call gate,
THEN #GP(segment selector); FI;
FI;
Depending on type and access rights:
GO TO CONFORMING-CODE-SEGMENT;
GO TO NONCONFORMING-CODE-SEGMENT;
GO TO CALL-GATE;
GO TO TASK-GATE;
GO TO TASK-STATE-SEGMENT;
FI;
CONFORMING-CODE-SEGMENT:
IF L-Bit = 1 and D-BIT = 1 and IA32_EFER.LMA = 1
THEN GP(new code segment selector); FI;
IF DPL > CPL
THEN #GP(new code segment selector); FI;
IF segment not present
THEN #NP(new code segment selector); FI;
IF stack not large enough for return address
THEN #SS(0); FI;
tempEIP ? DEST(Offset);
IF OperandSize = 16
THEN tempEIP ? tempEIP AND 0000FFFFH; FI; (* Clear upper 16 bits *)
IF (EFER.LMA = 0 or target mode = Compatibility mode) and (tempEIP outside new code
segment limit)
THEN #GP(0); FI;
IF tempEIP is non-canonical
THEN #GP(0); FI;
IF OperandSize = 32
THEN
Push(CS); (* Padded with 16 high-order bits *)
Push(EIP);
CS ? DEST(CodeSegmentSelector);
(* Segment descriptor information also loaded *)
CS(RPL) ? CPL;
EIP ? tempEIP;
ELSE
IF OperandSize = 16
THEN
Push(CS);
Push(IP);
CS ? DEST(CodeSegmentSelector);
(* Segment descriptor information also loaded *)
CS(RPL) ? CPL;
EIP ? tempEIP;
ELSE (* OperandSize = 64 *)
Push(CS); (* Padded with 48 high-order bits *)
Push(RIP);
CS ? DEST(CodeSegmentSelector);
(* Segment descriptor information also loaded *)
CS(RPL) ? CPL;
RIP ? tempEIP;
FI;
FI;
END;
Posted on 2009-08-07 11:31:45 by asmdna
you can also read the source code of OllyDBG's engine....
http://www.pediy.com/sourcecode/disassemblers/disasm/disasm.zip
assembl.c
asmserv.c
Posted on 2009-08-07 11:43:06 by asmdna