Intro x86 Part 2: More Examples and Analysis: Xeno Kovah - 2009/2010 Xkovah at Gmail
Intro x86 Part 2: More Examples and Analysis: Xeno Kovah - 2009/2010 Xkovah at Gmail
1
Approved for Public Release: 10-3348. Distribution Unlimited
Control Flow
Two forms of control flow
Conditional - go somewhere if a condition is met. Think if s,
switches, loops
Unconditional - go somewhere no matter what. Procedure
calls, goto, exceptions, interrupts.
Example2.999repeating.c:
(I missed this when I reordered slides and then didn t want to change
everything else again. Also, VS orders projects alphabetically, otherwise I
would have just called it GotoExample.c. Say lah vee :P)
//Goto example
#include <stdio.h>
int main(){
goto mylabel;
printf("skipped\n");
mylabel:
printf("goto ftw!\n");
return 0xf00d;
}
00401010
00401011
00401013
00401015
0040101A
00401020
mylabel:
00401023
00401028
0040102E
00401031
00401036
00401037
push
mov
jmp
push
call
add
ebp
ebp,esp
00401023
405000h
dword ptr ds:[00406230h]
esp,4
push
call
add
mov
pop
ret
40500Ch
dword ptr ds:[00406230h]
esp,4
eax,0F00Dh
ebp
JMP - Jump
10
Example3.c
(Remain calm)
int main(){
int a=1, b=2;
if(a == b){
return 1;
}
if(a > b){
return 2;
}
if(a < b){
return 3;
}
return 0xdefea7;
}
Jcc
main:
00401010
00401011
00401013
00401016
0040101D
00401024
00401027
0040102A
0040102C
00401031
00401033
00401036
00401039
0040103B
00401040
00401042
00401045
00401048
0040104A
0040104F
00401051
00401056
00401058
00401059
push
mov
sub
mov
mov
mov
cmp
jne
mov
jmp
mov
cmp
jle
mov
jmp
mov
cmp
jge
mov
jmp
mov
mov
pop
ret
ebp
ebp,esp
esp,8
dword ptr [ebp-4],1
dword ptr [ebp-8],2
eax,dword ptr [ebp-4]
eax,dword ptr [ebp-8]
00401033
eax,1
00401056
ecx,dword ptr [ebp-4]
ecx,dword ptr [ebp-8]
00401042
eax,2
00401056
edx,dword ptr [ebp-4]
edx,dword ptr [ebp-8]
00401051
eax,3
00401056
eax,0DEFEA7h
esp,ebp
ebp
6
11
Book p. 137
JZ/JE: if ZF == 1
JNZ/JNE: if ZF == 0
JLE/JNG : if ZF == 1 or SF != OF
JGE/JNL : if SF == OF
JBE: if CF == 1 OR ZF == 1
JB: if CF == 1
Note: Don t get hung up on memorizing which flags
are set for what. More often than not, you will be
running code in a debugger, not just reading it. In the
debugger you can just look at eflags and/or watch
whether it takes a jump.
9
Flag setting
Before you can do a conditional jump,
you need something to set the condition
flags for you.
Typically done with CMP, TEST, or
whatever instructions are already inline
and happen to have flag-setting sideeffects
10
12
11
13
12
Example4.c
#define MASK 0x100
int main(){
int a=0x1301;
if(a & MASK){
return 1; jcc
}
else{
return 2;
}
}
Eventually found out
why there are 2 jmps!
(no optimization, so simple compiler rules)
main:
00401010
00401011
00401013
00401014
0040101B
0040101E
00401023
00401025
0040102A
0040102C
0040102E
00401033
00401035
00401036
push
mov
push
mov
mov
and
je
mov
jmp
jmp
mov
mov
pop
ret
ebp
ebp,esp
ecx
dword ptr [ebp-4],1301h
eax,dword ptr [ebp-4]
eax,100h
0040102E
eax,1
I actually
00401033
expected
00401033
a TEST,
eax,2
because
esp,ebp
the result
ebp
isn't
stored
13
Refresher - Boolean
( bitwise ) logic
AND
0
0
1
1
0
1
0
1
Operands
&
0
0
0
1
Result
0
0
1
1
OR
0
1
0
1
0
1
1
1
XOR
0
0
1
1
0
1
0
1
0
1
1
0
NOT ~
0 1
1 0
14
14
AND
AND
result
result
Book p. 231
15
15
or al, 0x42
OR
OR
result
result
Book p. 231
16
16
XOR
OR
result
result
Book p. 231
17
17
not al
not [al+bl]
NOT
al
0x10000000
result
bl
0x00001234
al+bl
0x10001234
[al+bl]
NOT
00000000b
result
11111111b
18
main:
00401010
00401011
00401013
00401014
0040101B
0040101D
00401020
00401023
00401026
0040102A
0040102C
0040102F
00401030
00401035
0040103B
0040103E
00401040
00401042
00401044
00401045
push
mov
push
mov
jmp
mov
add
mov
cmp
jge
mov
push
push
call
add
jmp
xor
mov
pop
ret
ebp
ebp,esp
ecx
dword ptr [ebp-4],0
00401026
eax,dword ptr [ebp-4]
eax,1
dword ptr [ebp-4],eax
dword ptr [ebp-4],0Ah
00401040
ecx,dword ptr [ebp-4]
ecx
405000h
dword ptr ds:[00406230h]
esp,8
0040101D
eax,eax
esp,ebp
19
ebp
NOP
PUSH/POP
CALL/RET
MOV/LEA
ADD/SUB
JMP/Jcc
CMP/TEST
AND/OR/XOR/NOT
20
Example6.c
//Multiply and divide transformations
//New instructions:
//shl - Shift Left, shr - Shift Right
int main(){
unsigned int a, b, c;
a = 0x40;
b = a * 8;
c = b / 16;
return c;
}
main:
push
mov
sub
mov
mov
shl
mov
mov
shr
mov
mov
mov
pop
ret
ebp
ebp,esp
esp,0Ch
dword ptr [ebp-4],40h
eax,dword ptr [ebp-4]
eax,3
dword ptr [ebp-8],eax
ecx,dword ptr [ebp-8]
ecx,4
dword ptr [ebp-0Ch],ecx
eax,dword ptr [ebp-0Ch]
esp,ebp
ebp
21
Book p. 224
18
shl cl, 2
00110011b (cl - 0x33)
result
shl cl, 3
00110011b (cl - 0x33)
result 10011000b (cl - 0x98) CF = 1
22
Book p. 225
19
shr cl, 2
shr cl, 3
23
Example7.c
//Multiply and divide operations
//when the operand is not a
//power of two
//New instructions: imul, div
int main(){
unsigned int a = 1;
a = a * 6;
a = a / 3;
return 0x2bad;
}
main:
push
mov
push
mov
mov
imul
mov
mov
xor
mov
div
mov
mov
mov
pop
ret
ebp
ebp,esp
ecx
dword ptr [ebp-4],1
eax,dword ptr [ebp-4]
eax,eax,6
dword ptr [ebp-4],eax
eax,dword ptr [ebp-4]
edx,edx
ecx,3
eax,ecx
dword ptr [ebp-4],eax
eax,2BADh
esp,ebp
ebp
24
Book p. 218
20
initial
edx
eax
r/m32(ecx)
eax
r/m32(ecx)
eax
r/m32(ecx)
0x0
0x44000000
0x4
0x20
0x4
0x20
0x4
result
edx
eax
r/m32(ecx)
eax
r/m32(ecx)
eax
r/m32(ecx)
0x1
0x10000000
0x4
0x80
0x4
0x18
0x4
Book p. 221
21
initial
ax
r/m8(cx)
edx
eax
r/m32(ecx)
0x8
0x3
0x0
0x8
0x3
operation
div ax, cx
ah
al
edx
eax
r/m32(ecx)
0x2
0x2
0x1
0x2
0x3
result
26
Example8.c
//VisualStudio runtime check
//buffer initialization
//auto-generated code
//New instruction: rep stos
int main(){
char buf[40];
buf[39] = 42;
return 0xb100d;
}
27
Example8.c
main:
00401010
00401011
00401013
00401016
00401017
0040101A
0040101F
00401024
00401026
0040102A
0040102F
00401030
00401032
00401033
00401039
0040103E
0040103F
00401040
00401041
00401043
00401044
push
ebp
mov
ebp,esp
sub
esp,30h
push
edi
lea
edi,[ebp-30h]
mov
ecx,0Ch
mov
eax,0CCCCCCCCh
rep stos dword ptr es:[edi]
mov
byte ptr [ebp-5],2Ah
mov
eax,0B100Dh
push
edx
mov
ecx,ebp
push
eax
lea
edx,[ (401048h)]
call
_RTC_CheckStackVars (4010B0h)
pop
eax
pop
edx
pop
edi
mov
esp,ebp
pop
ebp
ret
28
22
Book p. 284
A: Compiler-auto-generated code.
From the stack frames runtime
check option. This is enabled by
default in the debug build.
Disabling this option removes the
compiler-generated code.
31
push
mov
sub
mov
mov
mov
pop
ret
ebp
ebp,esp
esp,28h
byte ptr [ebp-1],2Ah
eax,0B100Dh
esp,ebp
ebp
32
Example9.c
Journey to the center of memcpy()
main:
00401010
//Journey to the center of memcpy
00401011
#include <stdio.h>
00401013
00401016
typedef struct mystruct{
0040101D
int var1;
char var2[4];
0040101F
} mystruct_t;
00401022
00401023
int main(){
00401026
mystruct_t a, b;
00401027
a.var1 = 0xFF;
memcpy(&b, &a, sizeof(mystruct_t)); 0040102C
0040102F
return 0xAce0Ba5e;
00401034
}
00401036
00401037
push
mov
sub
mov
push
lea
push
lea
push
call
add
mov
mov
pop
ret
ebp
ebp,esp
esp,10h
dword ptr [a],0FFh
8
eax,[a]
eax
ecx,[b]
ecx
memcpy (401042h)
esp,0Ch
eax,0ACE0BA5Eh
esp,ebp
ebp
33
It begins
memcpy:
push
ebp
mov
ebp,esp
push
edi
;callee save
push
esi
;callee save
mov
esi,dword ptr [ebp+0Ch] ;2nd param - source ptr
mov
ecx,dword ptr [ebp+10h] ;3rd param - copy size
mov
edi,dword ptr [ebp+8] ;1st param - destination ptr
mov
eax,ecx ;copy length to eax
mov
edx,ecx ;another copy of length for later use
add
eax,esi ;eax now points to last byte of src copy
cmp
edi,esi ;edi (dst) esi (src) and set flags
jbe
1026ED30 ;jump if ZF = 1 or CF = 1
;It will execute different code if the dst == src or if the
destination is below (unsigned less than) the source (so jbe is
34
an unsigned edi <= esi check)
1026ED30 cmp
ecx,100h ;ecx - 0x100 and set flags
1026ED36 jb
1026ED57 ;jump if CF == 1
;Hmmmsince ecx is the length, it appears to do something
different based on whether the length is below 0x100 or not.
We could investigate the alternative path later if we wanted.
1026ED57 test
edi,3
;edi AND 0x3 and set flags
1026ED5D jne
1026ED74 ;jump if ZF == 0
;It is checking if either of the lower 2 bits of the destination
address are set. That is, if the address ends in 1, 2, or 3. If both
bits are 0, then the address can be said to be 4-byte-aligned.
so it s going to do something different based on whether the
destination is 4-byte-aligned or not.
35
1026ED5F shr
ecx,2 ;divide len by 4
1026ED62 and
edx,3 ;edx still contains a copy of ecx
1026ED65 cmp
ecx,8 ;ecx - 8 and set flags
1026ED68 jb
1026ED94 ;jump if CF == 1
;But we currently don t get to the next instruction 1026ED6A,
instead we jump to 1026ED94 :(
1026ED6A rep movs dword ptr es:[edi],dword ptr [esi]
1026ED6C jmp
dword ptr [edx*4+1026EE84h]
The rep movs is the target of this expedition.
Q: But how can we reach the rep mov?
A: Need to make it so that (length to copy) / 4 >= 8, so we
don't take the jump below
36
23
37
24
1026EE94
1026EE97
1026EE98
1026EE99
1026EE9A
mov
pop
pop
leave
ret
Book p. 309
38
39
NOP
PUSH/POP
CALL/RET
MOV/LEA
ADD/SUB
JMP/Jcc
CMP/TEST
AND/OR/XOR/NOT
SHR/SHL
IMUL/DIV
REP STOS, REP MOV
LEAVE
40
Homework
Write a program to find an instruction
we haven t covered, and report the
instruction tomorrow.
Instructions to be covered later which
don t count: SAL/SAR
Variations on jumps or the MUL/IDIV
variants of IMUL/DIV also don't count
Additional off-limits instructions:
anything floating point (since we're not
covering those in this class.)
41