Copy Link
Add to Bookmark
Report
BFi numero 12 file 07 English
-[ BFi - English version ]----------------------------------------------------
BFi is an e-zine written by the Italian hacker community.
Full source code and original Italian version are available at:
http://bfi.s0ftpj.org/dev/BFi12-dev-07.tar.gz
French translation available at:
http://bfi.s0ftpj.org/dev/fr/BFi12-dev-07-fr
English version translated by xenion <xenion@antifork.org>
------------------------------------------------------------------------------
==============================================================================
---------------------[ BFi12-dev - file 07 - 15/08/2003 ]---------------------
==============================================================================
-[ DiSCLAiMER ]---------------------------------------------------------------
The whole stuff contained in BFi has informative and educational
purposes only. In no event the authors could be considered liable
for damages caused to people or things due to the use of code,
programs, pieces of information, techniques published on the e-zine.
BFi is a free and autonomous way of expression; we, the authors,
are as free to write BFi as you are free to go on reading or to stop
doing it right now. Therefore, if you think you could be harmed by
the topics covered and/or by the way they are in, * stop reading
immediately and remove these files from your computer * .
You, the reader, will keep to youself all the responsabilities about
the use you will do of the information published on BFi by going on.
You are not allowed to post BFi to the newsgroups and to spread
*parts* of the magazine: please distribute BFi in its original and
complete form.
------------------------------------------------------------------------------
-[ HACKiNG ]------------------------------------------------------------------
---[ iMBW PR0T0C0L AND LiBRARY
-----[ xenion <xenion@antifork.org>
IMBW v1.0 protocol description and
libimbw v2.8 analysis
xenion <xenion@antifork.org>
--[ Contents
1 - Introduction
2 - The IMBW protocol
2.1 - Offered services
2.2 - The header
2.3 - Transmission sequence and flow management
2.4 - Connection creation: the three way handshake
2.5 - Connection termination
2.6 - Timeouts
2.7 - Keepalive packets
2.8 - Packets size
2.9 - The protocol and the library plugins
3 - Library internals
3.1 - Connections
3.2 - Cryptography
3.3 - Error handling and reporting
3.4 - Plugins
3.5 - Used libraries
4 - Library usage
4.1 - Functions, macros and extern vars
4.2 - Compiling your applications
5 - itools
5.1 - ishell
5.1.1 - examples
5.2 - ipipe
5.2.1 - examples
5.3 - inc
5.3.1 - examples
6 - Conclusion
--[ 1 - Introduction
This paper describes the IMBW protocol and one of its possible
implementations, an userspace library that offers:
- handling of n simultaneous connections
- simmetric cryptography
The protocol and the library born under the light of these
considerations:
- TCP connections are always detectable, analyzing the traffic
- There are backdoors that work through TCP, ICMP, UDP... packets, but
leaving the theoric aspect they're very uncomfortable, bringing to a
waste of precious resources
This project attempts to solve those problems: through the plugins we
choose the low level functions that will be used in order to send or
receive IMBW packets. Through them our IMBW connections will be entirely
encapsulated in every kind of IP packet (for example: ICMP, UDP, TCP,
IP OPTIONS).
In other words, with the imbw library you can handle full-duplex
connections through TCP, ICMP, UDP... packets, treating the connection
transparently, as a TCP connection.
--[ 2 - The IMBW protocol
It's a transport level protocol (expect for the packet checksum: it must be
handled by the used plugin) that proposes itself as an alternative to TCP.
I've introduced this stupid protocol only because it's simpler, anyway
it's also slower.
--[ 2.1 - Offered services
The IMBW protocol has been developed in order to offer a reliable
bytestream on a not-reliable network offering a service:
* reliable
* connection oriented
Taking care of:
* accepting data from the application level
* breaking data into segments, the TPDU's name
* delivering them to the network level, eventually retransmitting them
* receiving segments from the network level
* delivering data, in order, to the application level
--[ 2.2 - The header
Every segment is composed by:
* a header of 6 bytes
* the data to be delivered
The header fields have these functions:
- flags(1):
- FIN: used to release the connection
- SYN: used during the setup phase of the connection
- PUSH: it means that the packet contains data
- ACK: it means that the ACK field contains an acknowledge number
- port(1): It identifies the End Points of the connection: the TSAP.
Instead of other protocols as TCP and UDP the source port coincides to
the destination port.
- seq(2): sequence number of the packet
- ack(2): sequence number of the confirmed packet
--[ 2.3 - Transmission sequence and flow management
IMBW is a stop-and-wait (or one byte sliding window) protocol, let's see
the features:
- Stream Orientation: when two applications transfer data (bytestream),
the flow in the destination machine is given to the receiving
application exactly as it has been created by the source machine
- Full-duplex Connection: the connection permits a concurrent data
flow in every direction, without an apparent interaction
The receiver must be able to detect duplicate or lost segments through a
very important technique known as acknowledgement with retransmission.
This technique foresees the receiver to send an ack message to the sender
every received packet. The sender holds a copy of every sent packet and
removes it from the transmission buffer only after the reception of the
ack. The source user, after the transmission of a packet, waits to receive
the ack before sending the next one starting a timer used for timeouts
handling, and after its expiration, if no response has been received, it
resends the same packet. Protocols like this, where the sender waits a
confirmation ack, are called PAR (Positive Ack with Retransmission) or
ARQ (Automatic Repeat Request).
Sender (infinite loop, [seq] is the sequence field of a packet):
1. n_seq = X
2. n_seq = n_seq + 1
3. it builds a packet and copies n_seq into [seq]
5. it delivers the data packet to the transport level
6. it resets the timer
7. it waits for an event:
- expired timer: goto 5.
- arrives an (empty) valid ack packet: goto 2.
Receiver (infinite loop, [seq] is the sequence field of a packet):
1. n_exp = X
2. n_exp = n_exp+1
3. it waits for an event:
* arrives a valid segment from transport level:
- if ([seq] == n_exp):
* it extracts the packet
* it delivers (if present) transported data to the application level
level
- it sends an ack packet (empty)
- goto 2.
* arrives a non valid packet: goto 3.
--[ 2.4 - Connection creation: the three way handshake
It needs to exchange three packets:
1) the client starts the connection (active open) sending a packet with
only the header where:
* flags : SYN
* seq : initial sequence number of the client
* ack : 0
2) The server responds (passive open) sending a packet with only the header
where:
* flags : SYN
* seq : initial sequence number of the server
* ack : initial sequence number of the client
3) The client responds sending a packet with only the header where:
* flags : ACK
* seq : initial sequence number of the client
* ack : initial sequence number of the server
--[ 2.5 - Connection termination
It needs to exchange two packets:
1) The client starts the disconnection (active close) sending a packet
composed by the only header where:
* flags : FIN
* seq : X's sequence number
* ack : 0
2) The other ES responds (passive close) sending a packet composed by the
only header where:
* flags : ACK
* seq : 0
* ack : X's sequence number
Instead of TCP half-closed connections are not handled and this causes a
drastic simplification of the protocol.
--[ 2.6 - Timeouts
The reception of a packet from the other End System is confirmed through an
ack packet. The retransmission is handled through a timer, after n
retransmissions the connection fails.
--[ 2.7 - Keepalive packets
When the connection inactivity timeout exipres, a PUSH packet with the data
field null is sent. This implies an ack packet from the other End System.
--[ 2.8 - Packets size
IP packet fragmentation should be a level 3 (network) service, anyway we
need to avoid it. This problem will be solved in a future version of the
protocol, considering the userspace resources.
Let's see what is the MTU and the Path MTU, the cause of the problem: a
DataLink level characteristic is the maximum limit of the frame that we can
transmit. This limit depends by the specific protocol details, it isn't
only or always only a characteristic of the transport.
For example, CSMA/CD (IEEE 802.3) has a data limit of 1500 bytes. This
limit is called MTU (Maximum Transmission Unit). Packets larger than the
MTU must be fragmented.
+-------------------------+-------+
| Interface | MTU |
+-------------------------+-------+
| Hyperchannel | 65535 |
| 16 Mbits/sec Token Ring | 17914 |
| 4 Mbits/sec Token Ring | 4464 |
| FDDI | 4352 |
| Ethernet | 1500 |
| PPP | 1500 |
| X.25 | 576 |
+-------------------------+-------+
In the communication between two stations through a lot of networks (like
internet) the minimum MTU of the path is called Path MTU. This value
estabilishes the maximum size of a packet and over this size all packets
will be fragmented. Beware, the Path MTU is not symmetrical and it may be
different in the two route directions.
There's an IP protocol characteristic that is useful for our purposes: all
computers, as defined by the IP protocol, must be able to accept
datagrams of 576 bytes, fragmented or not. All computers that want to
exceed this limit must assure themselves the receiver is capable of
receiving them. This allows us to send data in every situation, the
problem is to define the maximum size.
At the end, there isn't a perfect value, 1000-1400 should not cause
problems (but everything will appear really slow). If you experiment
this situation:
- succesful connection creation
- connection lost, while transferring data
the reason may be the too high value
--[ 2.9 - The protocol and the library plugins
The IMBW packets aren't directly sent or received from the network
interface:
- when an IMBW packet must be delivered, a plugin exported function is
called. This function encapsules it into a transport level packet,
using the added header in order to handle the IMBW packet checksum.
After doing some things it sends it through the network interface.
- when something is read from the network interface, a plugin exported
function is called. After some checks (checksum,... ), if it looks as
an IMBW encapsulated packet, the envelope is removed and the function
returns the IMBW packet.
An example:
|--------------------------|
| IP header |
|--------------------------|
| ICMP header |
|--------------------------|
| signature (optional) |
|--------------------------|
| IMBW header |
|--------------------------|
| IMBW payload |
|--------------------------|
More details in 3.4.
--[ 3 - Library Internals
The IMBW stack is managed through an interface composed by some macros,
functions and exported structs. Internally two threads are used:
- [imbw_main]:
it analyzes the network traffic, looking for IMBW packets, and
handles the outgoing data flow.
- [imbw_timeouts]:
it handles everything related to packet timeouts: retransmission
and timed out connections.
For simplicity, since now on we'll call these two threads and the other
used resources "IMBW stack".
--[ 3.1 - The Connections
The connections are handled in a transparent way through the so called
local sockets (or Unix domain sockets): a communication mechanism
very similar to the pipes, but without the problem of the
unidirectionality of the data flow. Internally they are represented
with an imbw_connection_list struct list.
The pair of connected sockets used in order to handle every connection
is internally created where necessary. We can write and read on both
of them, one is internally used by the library, the other one is only
used by the application, and we've that:
- when a packet is received and its connection recognized (port, seq
number, src ip, dst ip) an ack packet is sent back and the data
component (if present) flies with a write(fd[0],bufx,lenx) to the
application that will catch it through a read(fd[1],bufz,lenz).
- when the application sends something, calling a write(fd[1], bufy,
leny), the [imbw_main] thread receives the data through a read(fd[0],
bufk, lenk) and sends it to the other End System. The channel (in this
direction) is blocked until an ack packet is received.
It's possible to create two connection types:
- outgoing: they are created through the imbw_connect() function.
- listening: they are created through the imbw_listen() function and
accepted through the imbw_accept() function. There isn't a queue of
pending connections, only the first request is handled. When the
connection reaches the ESTABILISHED or the DEAD state (in case of
timeout) a new listening connection must be created. (DEAD connections
are removed by the [imbw_main] thread)
--[ 3.2 - Cryptography
Blowfish is a symmetric block cipher that can be used as a drop-in
replacement for DES or IDEA. It takes a variable-length key, from 32 bits
to 448 bits, making it ideal for both domestic and exportable use. Blowfish
was designed in 1993 by Bruce Schneier as a fast, free alternative to
existing encryption algorithms. Since then it has been analyzed
considerably, and it is slowly gaining acceptance as a strong encryption
algorithm. It is quite a bit faster than DES, and much faster than IDEA or
RC2. Blowfish isn't patented and it's public.
Connections aren't ciphered, only the channeled data is ciphered. Every
connection is handled with its own blowfish key. The crypto support does
not protect against replay attack and does not offer any kind of
authentication.
--[ 3.3 - Error handling and reporting
There are two different error types:
- internal errors: they occur in [imbw_main], [imbw_timeouts] causing the
IMBW stack death (the two threads and all the connections are closed).
The error notify is managed internally and it's recognizable through
the imbw_check_errors() function. All the library interface functions
call internally the imbw_check_errors() function, if there is a problem
they notify it through the return value.
- external errors: they occur in the library interface functions and they
refer to a single connection (excluding imbw_init()), causing a forced
close. The error notify is managed through the return value.
--[ 3.4 - Plugins
The plugins are used in order to handle at low level the packet
transmission and reception, making libimbw adapting itself to the
situation. There are two kind of plugins:
- SEND: it handles only the packet transmission
- RECV: it handles only the packet reception
this function is exported only by RECV plugins:
IMBW_G_INLINE_FUNC int imbw_plugin_XXX_recv(const u_char * packet,
u_int32_t length);
It's used only by the [imbw_main] thread, working as an intermediary
between the pcap library and the plugin. It recognizes incoming packets,
loading them into an imbw_packet_struct struct.
This function is exported only by SEND plugins:
IMBW_G_INLINE_FUNC int imbw_plugin_XXX_send(u_int32_t saddr,
u_int32_t daddr,
unsigned char *payload,
u_int32_t length);
It's used by [main], [imbw_main], [imbw_timeouts] threads. Its sends a
single packet.
These functions are exported by all plugins:
int imbw_plugin_XXX_init();
It initializes the plugin, reserving the requested resources.
int imbw_plugin_XXX_destroy();
It frees the memory reserved by the plugin resources.
All the plugins are built-in, only 2 are used at runtime: one of type SEND
and the other one of type RECV.
In order to speed up the packet reception all the transmitted packets can
be signed (a string before the IMBW header). This also ensures ourselves
that anybody else can estabilish connections (assuming obviously that
anybody else knows the signature).
--[ 3.5 - Used libraries
It uses three libraries:
- libpthread (LinuxThreads)
- libpcap
it needs root privileges to open the capturing socket.. this is
a big disadvantage.
- libcrypto (openssl)
--[ 4 - Library usage
This version works only under linux.. sigh. The library can attach only one
network interface at a time. Yes, they look as problems, not features :P
--[ 4.1 - Functions, macro and extern vars
Summary
extern imbw_plugin_struct imbw_plugins[];
extern imbw_opt_struct imbw_opt;
extern char *imbw_errors_buf;
extern pthread_mutex_t imbw_ipfromlong_mutex;
int imbw_init();
void imbw_destroy();
int imbw_listen(u_int16_t port, void *passphrase,
u_int32_t len);
int imbw_accept(int fd);
int imbw_connect(u_int32_t daddr, u_int16_t port, int t,
void *passphrase, u_int32_t len);
u_int32_t imbw_getlongbyname(char *host);
IMBW_G_INLINE_FUNC int imbw_check_errors();
int imbw_thread_add(pthread_t id, char *name, u_char type);
int imbw_thread_create(void *(*start_routine) (void *),
void *arg, int detached);
void imbw_thread_remove_me();
int imbw_thread_sigset_block(int n, ...);
int imbw_thread_sigset_unblock(int n, ...);
void imbw_close_fds_expect012(int fd);
IMBW_G_INLINE_FUNC void imbw_debug(char *f, int l, char *pattern, ...);
char *imbw_ipfromlong(unsigned long s_addr);
Description
imbw_init() initializes the structs and threads internally handled, if
there is an error the return value is -1. This function internally
calls the IMBW_SIGSET_BLOCK macro.
imbw_destroy() frees the resources used by the library. It handles the
disconnections of the connections in ESTABILISHED and LISTEN state.
imbw_listen() creates a connection in listening state on the port port.
The return value is the connection associated fd, if an error occurs
the return value is -1. The connection key of length len is pointed by
passphrase.
imbw_accept() accepts a connection created through the imbw_listen()
function. The thread is blocked until a connection request arrives. If an
error occurs the return value is -1.
imwb_connect() attemts to estabilish a connection to daddr:port. t is the
timeout and is internally handled. If t == 0, the timeout will be
maximized to IMBW_CONNECTION_TIMEOUT. The connection key of length len is
pointed by passphrase. -1 is returned if an error occurs, otherwise the
return value is a descriptor referencing the socket.
imbw_check_errors() checks the IMBW stack status. All the library
interface functions call internally the imbw_check_errors() function. If
an internal error occurs the return value is 1, otherwise 0.
imbw_close_fds_expect012() closes all fds except 0,1,fd.
imbw_getlongbyname() resolves the string pointed by host (an hostname or
an IPv4 address in standard dot notation).
imbw_ipfromlong() returns a string statically allocated that points to
the IPv4 s_addr in standard dotted notation. It internally uses the
inet_ntoa() function. To use these two functions is necessary a lock of
the imbw_ipfromlong_mutex mutex. This function is used by the library
only if the debugging is enabled.
IMBW_SIGSET_BLOCK blocks some signals sent to the thread.
IMBW_SIGSET_UNBLOCK unblocks some signals sent to the thread.
IMBW_DEBUG is used to trace the execution of the registered threads
through imbw_thread_add(). logfile ('./imbw.main-pid.log') is opened with
flags "a+" through the imbw_init() function.
imbw_thread_add() adds a thread to the list of the registered threads.
type is the type of the thread:
- IMBW_NOTRELATED: library (and plugin) threads
- IMBW_RELATED: other threads (main, ..)
Useful only for debugging.
imbw_thread_remove_me() removes the current thread from the thread list.
imbw_close_log() closes the logfile. It's called internally by the
imbw_destroy() function.
extern imbw_opt_struct imbw_opt: you can setup the library behaviour
initializing this struct:
typedef struct {
u_int16_t pmsize;
u_int16_t packet_attempts;
u_int16_t packet_timeout;
u_int16_t keepalive_timeout;
char *dev;
u_int32_t addr;
char *sign;
int plugin_send;
int plugin_recv;
char *plugin_send_options;
char *plugin_recv_options;
} imbw_opt_struct;
pmsize is the MTU less the IMBW header size (if the SEND plugin doesn't
add other stuff). after packet_attempts retransmission attempts the
connection is considered lost. the ack timeout is packet_timeout.
keepalive_timeout is the connection inactivity timeout. dev the network
interface attached by the IMBW stack. Through addr we can force a local
address (ignoring the network interface address). sign points to the
signature string. The SEND plugin id is plugin_send, the RECV plugin id
is plugin_recv. plugin_send_options and plugin_recv_options point to the
plugin parameters.
extern imbw_plugin_struct imbw_plugins[]: it references the available
plugins. Take a look to itools...
LIBIMBW_VER identifies the libimbw version
On error, imbw_errors_buf always points to a static string with a
description. If there are more than one thread handled by the
application, you won't be able to identify which one caused the error.
To use inet_ntoa or imbw_ipfromlong() you must lock the
imbw_ipfromlong_mutex mutex.
--[ 4.2 - Compiling your applications
We need 3 files: imbw.a, libimbw-config, imbw.h:
cc `../libimbw/libimbw-config --cflags` \
-I../libimbw \
`../libimbw/libimbw-config --defines` \
file.c \
imbw.a \
imbw_packet_x.a \
`../libimbw/libimbw-config --libs` \
-o file
--[ 5 - itools
This is a little tools suite, working with libimbw.
--[ 5.1 - ishell
it's an internet ``super-server'' (like inetd) and allows the remote
execution of commands (like rsh). The command list associated with their
ports and the 'special' port are defined statically in ishell.h .
Yes, it looks like a backdoor :)
--[ 5.1.1 - examples
1) ./ishell
displays the command syntax and the available plugins.
2) ./ishell -L
displays the command list associated with their ports.
3) ./ishell -i eth0 -S 43302 -p sventek -G2:3
it listens on the eth0 network interface, the packets signature is
"43302" and the passphrase is sventek. Two plugins are used: #2 (SEND
type) and #3 (RECV type). If from the plugin list they are:
[..]
02 send sendtcp v0.1, opt: [SRCPORT:DSTPORT:FLAGS]
03 recv recvtcp v0.1, opt: []
[..]
then every sent or received IMBW packet is encapsulated into a TCP
packet.
4) ./ishell -i eth0 -S 43302 -p sventek -G2:1 -a 2083:21:2
it listens on the eth0 network interface, the packets signature is
"43302" and the passphrase is sventek. Two plugins are used: #2 (SEND
type) and #1 (RECV type). If from the plugin list they are:
[..]
01 recv recvicmp v0.1, opt: []
02 send sendtcp v0.1, opt: [SRCPORT:DSTPORT:FLAGS]
[..]
then all sent packets will be encapsulated into TCP packets and all
received packets into ICMP packets. At the end, The -A option is used:
the TCP packets will have src port 2083, dstport 21 and 2 (SYN) as
flags.
5) ./ishell -w 100 -i ppp0 -S 43302 -p sventek -G2:1
it listens on the ppp0 network interface with the same signature,
passphrase and used plugins of the last example. When executed, it
wailts 100 seconds and than does his things. The pause is done because
we must be sure that the Point-to-Point link exists... useful if started
in an automated way after the boot phase, before the network devices
initialization.
--[ 5.2 - ipipe
it's a transport layer bridge (IMBW/TCP).
--[ 5.2.1 - examples
1) ./ipipe -D -s any:23 -d 192.168.1.3:0 -e 2 -i eth0 -S 43302 \
-p sventek -G2:3
the pipe type is defined by the -e option, you can choose between:
0: IMBW > IMBW
1: IMBW > TCP
2: TCP > IMBW
3: TCP > TCP
in our example the TCP port 23 will listen for connections on all
interfaces. When a connection is estabilished, an IMBW connection is
attempted towards the 192.168.1.3 addr, IMBW port 0 (the IMBW ports are
comprised between 0 and 255). The exchange of IMBW packets is done only
through the eth0 network interface, the packets signature is "43302",
the passphrase is sventek and the plugins #2 and #3 are used. The -D
option is used in order to dump all connections in files in current
directory.
2) ./ipipe -s any:67 -d 192.168.1.3:6667 -e 1 -i ppp0 \
-S 43302 -p sventek -G2:3
we want to allow internet users to use a private ircd, reachable only
from the internal lan. It listends on the IMBW port 67 on the ppp0
network interface. Yes any is ignored... if the pipe type is 0 or 1 the
source address isn't used: every connection attempt from the ppp0
interface towards the IMBW port 67 is considered valid.
--[ 5.3 - inc
it establishes an IMBW connection and acks with the other ES through
stdin/stdout.
--[ 5.3.1 - examples
1) ./inc -d 192.168.1.10:0 -i eth0 -S 43302 -p sventek -G2:3
on 192.168.1.10 ishell is running, the IMBW port 0 is associed with the
execution of '/bin/sh -i'. something like an IMBW bindshell ;)
2) echo 'cat /etc/passwd' | ./inc -d 192.168.1.10:254 \
-i eth0 -S 43302 -p sventek -G2:3
on 192.168.1.10 ishell is running, the IMBW port 254 is the 'special'
one that allows the remote exectuion of commands: As soon as the
connection is estabilished a stream of bytes ending with '\n' is
expected (the command) and than it is executed. The proposed example
executes on the remote host the 'cat /etc/passwd' command, visualizing
the output on stdout.
6 - Conclusion
libimbw may be used in order to develop next generation backdoors and other
complex stuff, easily: thanks to the plugin subsystem, this library can
estabilish full-duplex connections stealthly through firewalls and Intrusion
Detection Systems.
At last, many thanks to antifork.org guys, their passive contribute through
the cvs stuff was great! and a big thanks to darkangel who supported this
project with patience and knowledge, making also a first english translation
of this paper.
This is all, have fun and send me patches and new plugins! every contribute
will be appreciated ;-)
uh, IMBW stands for 'I Might Be Wrong', a RH song.
EOF
-[ WEB ]----------------------------------------------------------------------
http://bfi.s0ftpj.org [main site - IT]
http://bfi.cx [mirror - IT]
http://bfi.freaknet.org [mirror - AT]
http://bfi.anomalistic.org [mirror - SG]
-[ E-MAiL ]-------------------------------------------------------------------
bfi@s0ftpj.org
-[ PGP ]----------------------------------------------------------------------
-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: 2.6.3i
mQENAzZsSu8AAAEIAM5FrActPz32W1AbxJ/LDG7bB371rhB1aG7/AzDEkXH67nni
DrMRyP+0u4tCTGizOGof0s/YDm2hH4jh+aGO9djJBzIEU8p1dvY677uw6oVCM374
nkjbyDjvBeuJVooKo+J6yGZuUq7jVgBKsR0uklfe5/0TUXsVva9b1pBfxqynK5OO
lQGJuq7g79jTSTqsa0mbFFxAlFq5GZmL+fnZdjWGI0c2pZrz+Tdj2+Ic3dl9dWax
iuy9Bp4Bq+H0mpCmnvwTMVdS2c+99s9unfnbzGvO6KqiwZzIWU9pQeK+v7W6vPa3
TbGHwwH4iaAWQH0mm7v+KdpMzqUPucgvfugfx+kABRO0FUJmSTk4IDxiZmk5OEB1
c2EubmV0PokBFQMFEDZsSu+5yC9+6B/H6QEBb6EIAMRP40T7m4Y1arNkj5enWC/b
a6M4oog42xr9UHOd8X2cOBBNB8qTe+dhBIhPX0fDJnnCr0WuEQ+eiw0YHJKyk5ql
GB/UkRH/hR4IpA0alUUjEYjTqL5HZmW9phMA9xiTAqoNhmXaIh7MVaYmcxhXwoOo
WYOaYoklxxA5qZxOwIXRxlmaN48SKsQuPrSrHwTdKxd+qB7QDU83h8nQ7dB4MAse
gDvMUdspekxAX8XBikXLvVuT0ai4xd8o8owWNR5fQAsNkbrdjOUWrOs0dbFx2K9J
l3XqeKl3XEgLvVG8JyhloKl65h9rUyw6Ek5hvb5ROuyS/lAGGWvxv2YJrN8ABLo=
=o7CG
-----END PGP PUBLIC KEY BLOCK-----
==============================================================================
-----------------------------------[ EOF ]------------------------------------
==============================================================================