This is an example how to use Vivisect.
Vivisect is a cool collection of tools for both static and dynamic analysis of binaries.
It supports x86, x86_64, and ARM binaries. Also runs on multiple platforms Linux, Win and osX
You are probably wondering what is the link with this blog.
It is all written in Python. Yes all of it. From the multi platform debugger through the disassembly
engine up to the emulator and GUI. It's a piece of beauty.
The code base is very nice. It uses introspection beautifiers etc. It's modular and well structured.
That actually proves the people behind it are highly skilled with the language and enjoy it.
For this presentation we will crack a middle difficulty crackme from http://crackmes.de/
The binary used for the case is Tryger's keygen_rivendel
You can also download the whole solution from http://crackmes.de/users/tryger/keygen_rivendel/solutions/bat.serjo
SPOILER :)
DEFAULT USER: \n
DEFAULT PASS: \n
But that's not interesting :) There is no goal in this other than fun :D
This crackme is one small time, dirty, wanna be gangsta.
$ gdb -q ./breakme
Reading symbols from ./breakme...Segmentation fault
Ayee gangsta?
$ nm ./breakme
08049e8c d (null)
080484b0 t (null)
080484e0 t (null)
....
Alright then let see how you do against Vivisect (https://github.com/vivisect)
$ ./vivbin -B ./breakme
Failed to find file for 0x08049fb8 (_edata) (and filelocal == True!)
Failed to find file for 0x08049fb8 (__bss_start) (and filelocal == True!)
Failed to find file for 0x08049fb8 (__TMC_END__) (and filelocal == True!)
Loaded (0.0513 sec) ./breakme
ANALYSIS TIME: 0.267040967941
stats: {'functions': 24, 'relocations': 0}
Saving workspace: ./breakme.viv
Hmm ain't that tough after all :)
First of all I would like to say that this crack me is a perfect example
for security through obscurity. Anti debug protections combined with
decoys and recursion for the check algorithm. It's so ahead in the game
obscurity that even a successful check of the key sounds dubious :)
You got it? or not! I don't really know.
Anti debug protection number one. Obviously something is wrong with the ELF header.
Wrong enough to crash gdb. I didn't spent much time figuring out what. Since the
kernel is able to load it and execute it. Also vivisect coped well with it.
Using vivisect analyze the __entry point of the program.
.text:0x080487b6 55 push ebp
.text:0x080487b7 89e5 mov ebp,esp
.text:0x080487b9 81ecb8000000 sub esp,184
.text:0x080487bf 6a00 push 0
.text:0x080487c1 6a01 push 1
.text:0x080487c3 6a00 push 0
.text:0x080487c5 6a00 push 0
.text:0x080487c7 e894fcffff call ptrace_08048460 ;<-- antidebug protection number two :)
.text:0x080487cc 83c410 add esp,16
.text:0x080487cf 85c0 test eax,eax
.text:0x080487d1 791a jns loc_080487ed
Hehe old school unix anti debug tricks. Ptrace your self so that nobody else can ptrace you :D
Then there's a check for the result. So what happens if you try to debug it with something else than gdb :)
python ./crack.py ~/examples/CRACKME/rivendel/breakme
You are debugging me, I don't like it :(
Hehe really bro? We'll see about that later.
Now lets continue with analyzing the flow of the program using the FuncGraph.
We notice that if ptrace succeeds we continue with some welcoming messages etc.
Then we read the user input. With fgets.
Spoiler. If fgets fails we end up jumping to 0x08048918.THIS IS A DECOY! everything after this is a decoy!
Yes the binary is 90% bullshit :) But I'm not sure I get the reset 10% either.
If getting the password fails it will also jump there!
The password is read using getc from the function @ 0x0804877b.
It must read 3 times more data from the input than the username length!
Then the (username, password, counter, tmpVar, userLen) are fed to the function @ 0x0804856b
This is where the magic happens 0x0804856b.
Give the function a glance at the FuncGraph.
- It's recursive
- It has multiple check points
- It has multiple direct exit(-1) points
- If you survive this function you pretty much 'own' the binary :)
- It takes multiple arguments
- On every cycle it makes a check of the currently calculated theoretical hash
- If the check fails you end up in the exit(-1) case.
- Otherwise continue recursion.
Check out the function in the Viv window
.text:0x0804856b
.text:0x0804856b FUNC: int cdecl breakme.magic( int arg0, int arg1, int arg2, int arg3, int arg4, ) [4 XREFS]
.text:0x0804856b
.text:0x0804856b Stack Variables:
.text:0x0804856b 20: int arg4
.text:0x0804856b 16: int arg3
.text:0x0804856b 12: int arg2
.text:0x0804856b 8: int arg1
.text:0x0804856b 4: int arg0
.text:0x0804856b -16: int local16
Here's what the arguments are - as seen @
.text:0x080488dc 83c410 add esp,16
.text:0x080488df 83ec0c sub esp,12
.text:0x080488e2 50 push eax ;ARG strlen_hashed_user
.text:0x080488e3 6a00 push 0 ;ARG 0
.text:0x080488e5 6a00 push 0 ;ARG 0
.text:0x080488e7 8d8557ffffff lea eax,dword [ebp - 169]
.text:0x080488ed 50 push eax ;ARG Password
.text:0x080488ee 8d45cf lea eax,dword [ebp - 49]
.text:0x080488f1 50 push eax ;ARG Hashed user
.text:0x080488f2 e874fcffff call breakme.magic
.text:0x080488f7 83c420 add esp,32
.text:0x080488fa 85c0 test eax,eax
.text:0x080488fc 7510 jnz loc_0804890e
.text:0x080488fe 83ec0c sub esp,12
.text:0x08048901 688e8c0408 push str_Yout got it, or _08048c8e ;bingo
.text:0x08048906 e8f5faffff call puts_08048400 ;puts_08048400()
.text:0x0804890b 83c410 add esp,16
.text:0x0804890e loc_0804890e: [1 XREFS]
.text:0x0804890e 83ec0c sub esp,12
.text:0x08048911 6a01 push 1 ;SUCCESS !!!
.text:0x08048913 e808fbffff call exit_08048420
In short breakme.magic(user, pwd, cnt, unk, userLen)
Also here you can see that if you survive the magic you are done.
Using the Symbolics window in Vivisect extract the results
- Using the simplified view extract all possible paths
- Sort them in a file.
- Try to figure out what all this means.
It sounds hard but is actually not.
In the Symbolics.txt you can find a log of my struggles.
Actually I didn't expect to get anything useful out of this.
But also didn't want to start debugging yet.
The results were actually pretty good.
In short I was able to make a skeleton of the algorithm
in a pseudo language quite fast.
def reverse(user, pwd, cnt, unk=0, userLen = len(user)):
if cnt == userLen*3:
return 0
if cnt < userLen * 2:
if cnt < userLen:
if pwd[cnt] == (unk+15) ^ user[cnt]
lvar = cnt+1
if cnt + 1 == userLen:
arg3 = ((unk + 15) ^ user[cnt]) - 10
reverse(user, pwd, cnt+1, arg3, userLen)
else
arg3 = ((unk + 15) ^ user[cnt])
reverse(user, pwd, cnt+1, arg3, userLen)
else
raise Exception("missed at %s %d %s" % (user, cnt, pwd))
else:
if pwd[cnt] != (18 - unk) ^ user[ (cnt/userLen) % userLen ]:
raise Exception("missed at %s %d %s" % (user, cnt, pwd))
else
lvar = cnt + 1
if cnt + 1 == userLen*2:
arg3 = (18 - unk) ^ user[ (cnt/userLen) % userLen ] + 113
reverse(user, pwd, cnt+1, arg3, userLen)
else
arg3 = (18 - unk) ^ user[ (cnt/userLen) % userLen ]
reverse(user, pwd, cnt+1, arg3, userLen)
else:
if pwd[cnt] == ((unk - 76) * 2) ^ user[ (cnt / userLen) % userLen ]:
lvar = cnt + 1
arg3 = ((unk - 76) * 2) ^ user[ (cnt / userLen) % userLen ]
reverse(user, pwd, cnt+1, arg3, userLen)
else
raise Exception("missed at %s %d %s" % (user, cnt, pwd))
From this I made a "generator" (still not 100% working :).
Problem. As it turns out you must enter non printable characters for the password.
What the hell. Redirecting input from file or if you're a shell ninja get it done somehow.
Guess the binary is supposed to be used as a part from a bigger system and called externaly
then the exit status is used to make the judgment.
serj@debian:~/examples/CRACKME/rivendel$ python keygen.py a
6ecf89
serj@debian:~/examples/CRACKME/rivendel$ ./breakme < input.raw
Keygen me... if you can ;-)
Have fun & Good luck!
User (1 - 40 chars): Password for the user a (3 bytes):
Yout got it, or not... ;)
Problem:
serj@debian:~/examples/CRACKME/rivendel$ python keygen.py plp
7fe281f777f7488808
serj@debian:~/examples/CRACKME/rivendel$ ./breakme < input.raw
Keygen me... if you can ;-)
Have fun & Good luck!
User (1 - 40 chars): Password for the user plp (9 bytes): WRONG SERIAL :-(
As mentioned before not 100% accurate.
Lets debug this little fucker. vtrace is powerful tool. Maybe a tid bit slow.
But powerful. Lets write a script that will runtime patch the binary to spit out the password.
Using vtrace:
- Patch the ptrace call so that execution proceeds as normal.
- Add instrumentation to print the calculated value for the password
- Hook the unwanted branch of every check manipulate it and jump to the wanted branch as if nothing happened.
I'm usint breakpoints for all this.
For example a breakpoint on the ptrace call instruction can manipulate the eip register and simply continue.
This effectively bypasses the ptrace protection.
class PtracePatch ( Breakpoint ):
def notify( self, event, trace ):
rctx = trace.getRegisterContext()
curaddr = rctx.getProgramCounter()
jumpaddr = curaddr + 5 #bytes: e894fcffff
rctx.setProgramCounter(jumpaddr)
Get it right :) Something similar for the branch and printing and the crack.py was ready.
Put the crack.py inside the vivisect folder in order to be able to resolve needed modules etc.
serj@debian:~/netstock/vivisect$ cp ~/examples/CRACKME/rivendel/crack.py ./
serj@debian:~/netstock/vivisect$ python ./crack.py ~/examples/CRACKME/rivendel/breakme
Keygen me... if you can ;-)
Have fun & Good luck!
User (1 - 40 chars): plp
Password for the user plp (9 bytes): aaaaaaaaa
Yout got it, or not... ;)
7f e2 81 eb 4b b7 c8 94 e0
serj@debian:~/examples/CRACKME/rivendel$ python ./keygen.py -use plp 7f e2 81 eb 4b b7 c8 94 e0
serj@debian:~/examples/CRACKME/rivendel$ ./breakme < input.raw
Keygen me... if you can ;-)
Have fun & Good luck!
User (1 - 40 chars): Password for the user plp (9 bytes):
Yout got it, or not... ;)
Problem solved :)
So you got it? or not. I still have no idea. But at least I have a keygen :D
And here is the script that does the job
'''
Created on Apr 24, 2015
@author: serj
'''
import sys
import errno
import struct
import envi
import envi.archs.i386 as e_i386
import vtrace
from vtrace.breakpoints import Breakpoint
class PtracePatch ( Breakpoint ):
def notify( self, event, trace ):
rctx = trace.getRegisterContext()
#self.resolveAddress( trace )
curaddr = rctx.getProgramCounter()
jumpaddr = curaddr + 5 #bytes: e894fcffff
#trace.setRegister( e_i386.REG_EIP, jumpaddr )
rctx.setProgramCounter(jumpaddr)
class BranchPatch ( Breakpoint ):
def setRedirectAddr(self, desiredAddr):
self.desiredAddr = desiredAddr
def notify( self, event, trace ):
rctx = trace.getRegisterContext()
rctx.setProgramCounter( self.desiredAddr )
#1 part
#0x080485b7
#2 part
#0x080485ec
#3 part
#0x08048622
class PrintAL ( Breakpoint ):
def notify( self, event, trace ):
rctx = trace.getRegisterContext()
al = rctx.getRegister(e_i386.REG_AL)
print '%.2x ' % al,
if __name__ == '__main__':
trace = vtrace.getTrace()
trace.execute('%s' % sys.argv[1])
trace.requireAttached()
#maps = trace.getMemoryMaps()
#for m in maps:
# print m
_ppach1 = PtracePatch(0x80487c7)
trace.addBreakpoint( _ppach1 )
_bb1 = BranchPatch(0x080485ca)
_bb1.setRedirectAddr(0x0804863c)
trace.addBreakpoint( _bb1 )
_bb2 = BranchPatch(0x080485ff)
_bb2.setRedirectAddr(0x0804866c)
trace.addBreakpoint( _bb2 )
_bb3 = BranchPatch(0x08048635)
_bb3.setRedirectAddr(0x080486a0)
trace.addBreakpoint( _bb3 )
_pal1 = PrintAL(0x080485b7)
trace.addBreakpoint( _pal1 )
_pal2 = PrintAL(0x080485ec)
trace.addBreakpoint( _pal2 )
_pal3 = PrintAL(0x08048622)
trace.addBreakpoint( _pal3 )
trace.setMode("RunForever", True)
trace.run()
15 minutes of python a day!
This is my drop back to the open source comunity. It is devoted to Python, the language I find myself using quite often to just-do-the-job. My small trips and tricks while i'm using it, how i use it and what for. And things like that.
Tuesday, September 22, 2015
Sunday, February 10, 2013
Controlling the network interfaces through Python, like a sir!
Ever wanted to be able to get all available network interfaces and control them through Python? Well so did I, thus I went on the web and started searching for such modules/packages that can do that. And I found. I found ethtool I also found netifaces and also this dionaea's getifaddrs and of course tons of questions about it on stackoverflow but they all seem to lack one important feature. Controlling the interface, meaning bringing it up, changing it's IP address etc. Correct me if I'm wrong. Thus I decided to create one that can.
In order to control a network interface in most Unix derivatives you need to deal with IOCTL - a obscure & useful system call used for everything you can imagine. For the purpose of manipulating a network interface we have to deal with one more hairy member of the Unix world.
Meet "struct ifreq":
struct ifreq
{
# define IFHWADDRLEN 6
# define IFNAMSIZ IF_NAMESIZE
union
{
char ifrn_name[IFNAMSIZ]; /* Interface name, e.g. "en0". */
} ifr_ifrn;
union
{
struct sockaddr ifru_addr;
struct sockaddr ifru_dstaddr;
struct sockaddr ifru_broadaddr;
struct sockaddr ifru_netmask;
struct sockaddr ifru_hwaddr;
short int ifru_flags;
int ifru_ivalue;
int ifru_mtu;
struct ifmap ifru_map;
char ifru_slave[IFNAMSIZ]; /* Just fits the size */
char ifru_newname[IFNAMSIZ];
__caddr_t ifru_data;
} ifr_ifru;
};
Hairy stuff, really hairy. Just tell me what sockaddr really is? Yeah right it's another union. What about ifmap? Just how many structures do you have to know to be able to work with this one. Well can you really blame the people who did this structure? It's not their fault, after it is used for a lot of things. I mean almost every action connected with a network interface is stuffed through ioctl using this structure. So instead of bragging about it's hair style lets consider the techniques we have in the Python world to deal with such structure.
- For one we can always make a C/C++ extension and hide the complexity there. This approach was taken by ethtool and netifaces. I don't like this approach much. First you can't benefit from Pythons features. Second the code base becomes quite bloated with very similar patterns like 'set ifreq struct value, call ioctl, handle return code' and I don't like it.
- A lot of answers on stackoverflow show how you can get or set a particular option of a network interface in pure python using the struct module. But can you imagine writing a function for every element of that ifreq structure like this:
def get_ip(iface = 'eth0'):
... ifreq = struct.pack('16sH14s', iface, socket.AF_INET, '\x00'*14)
... try:
... res = fcntl.ioctl(sockfd, SIOCGIFADDR, ifreq)
... except:
... return None
... ip = struct.unpack('16sH2x4s8x', res)[2]
... return socket.inet_ntoa(ip)
Code taken from http://stackoverflow.com/questions/166506/finding-local-ip-addresses-using-pythons-stdlib
- Then there's ctypes. The module that helps you exploit those C libraries without having to deal with C. Inspired by the dionaeas approach I decided that this is the one and only path I will take.
I want easy and intuitive access to the network interfaces. I wan't a class representing a interface. I wan't to be able to get and set values of this interface by simply accessing them like variables. I wan't pretty printing. I wan't short but working code with as little replication as possible. I wan't something like this:
#!/usr/bin/env python import pyiface #Get all available network interfaces allIfaces = PyIface.getIfaces() for iface in allIfaces: print iface #Get a specific interface by name eth0 = PyIface.Interface('eth0') #view eth0 info print eth0 #bring eth0 up eth0.flags = eth0.flags | IFF_UP #set ipv4 address of the interface eth0.addr = (socket.AF_INET, '1.2.3.4') #set ipv6 address of the interface eth0.addr = (socket.AF_INET6, '2001:0db8:85a3:0000:0000:8a2e:0370:7334')
Beautiful isn't it? How hard can it be? Wee not much indeed. Using Pythons property attributes it becomes a piece of cake like this :)
import sys import fcntl import struct import socket from ctypes import * from .ifreqioctls import * from binascii import hexlify flags2str = { IFF_UP: 'Interface is up.', IFF_BROADCAST: 'Broadcast address valid.', IFF_DEBUG: 'Turn on debugging.', IFF_LOOPBACK: 'Is a loopback net.', IFF_POINTOPOINT: 'Interface is point-to-point link.', IFF_NOTRAILERS: 'Avoid use of trailers.', IFF_RUNNING: 'Resources allocated.', IFF_NOARP: 'No address resolution protocol.', IFF_PROMISC: 'Receive all packets.', IFF_ALLMULTI: 'Receive all multicast packets.', IFF_MASTER: 'Master of a load balancer.', IFF_SLAVE: 'Slave of a load balancer.', IFF_MULTICAST: 'Supports multicast.', IFF_PORTSEL: 'Can set media type.', IFF_AUTOMEDIA: 'Auto media select active.', IFF_DYNAMIC: 'Dialup device with changing addresses.' } def flagsToStr(fin): ret = '' for k in flags2str.keys(): if fin & k: ret = ret +'\t'+ flags2str[k] + '\n' return ret class sockaddr_gen(Structure): _fields_ = [ ( "sa_family", c_uint16 ), ( "sa_data", (c_uint8 * 22) ) ] # AF_INET / IPv4 class in_addr(Structure): _pack_=1 _fields_ = [ ("s_addr", c_uint32), ] class sockaddr_in(Structure): _pack_=1 _fields_ = [ ("sin_family", c_ushort), ("sin_port", c_ushort), ("sin_addr", in_addr), ("sin_zero", (c_uint8 * 16) ), # padding ] # AF_INET6 / IPv6 class in6_u(Union): _pack_=1 _fields_ = [ ("u6_addr8", (c_uint8 * 16) ), ("u6_addr16", (c_uint16 * 8) ), ("u6_addr32", (c_uint32 * 4) ) ] class in6_addr(Structure): _pack_ = 1 _fields_ = [ ("in6_u", in6_u), ] class sockaddr_in6(Structure): _pack_=1 _fields_ = [ ("sin6_family", c_short), ("sin6_port", c_ushort), ("sin6_flowinfo", c_uint32), ("sin6_addr", in6_addr), ("sin6_scope_id", c_uint32), ] # AF_LINK / BSD|OSX class sockaddr_dl( Structure ): _fields_ = [ ("sdl_len", c_uint8 ), ("sdl_family", c_uint8 ), ("sdl_index", c_uint16 ), ("sdl_type", c_uint8 ), ("sdl_nlen", c_uint8 ), ("sdl_alen", c_uint8 ), ("sdl_slen", c_uint8 ) # ("sdl_data", (c_uint8 * 46) ) ] class sockaddr ( Union ): _pack_=1 _fields_ = [ ('gen', sockaddr_gen), ('in4', sockaddr_in ), ('in6', sockaddr_in6 ) ] class ifmap( Structure ): _pack_=1 _fields_ = [ ('mem_start', c_ulong), ('mem_end', c_ulong), ('base_addr', c_ushort), ('irq', c_ubyte ), ('dma', c_ubyte ), ('port', c_ubyte ) ] IFNAMSIZ = 16 IFHWADDRLEN = 6 class ifr_data( Union ): _pack_ = 1 _fields_ = [ ('ifr_addr', sockaddr), ('ifr_dstaddr', sockaddr), ('ifr_broadaddr',sockaddr), ('ifr_netmask', sockaddr), ('ifr_hwaddr', sockaddr), ('ifr_flags', c_short), ('ifr_ifindex', c_int), ('ifr_ifqlen', c_int), ('ifr_metric', c_int), ('ifr_mtu', c_int), ('ifr_map', ifmap), ('ifr_slave', (c_ubyte*IFNAMSIZ)), ('ifr_newname', (c_ubyte*IFNAMSIZ)), ('ifr_data', c_void_p) ] class ifreq( Structure ): _pack_=1 _fields_= [ ('ifr_name', (c_ubyte*IFNAMSIZ)), ('data', ifr_data) ] class Interface(object): """ Represents a network interface. Almost all interesting attributes are exported in the form of a variable. You can get or set this variable. For example: ifeth0 = Interface("eth0") print ifeth0.addr # will print the current address ... or ... ifeth0.addr = (AF_INET, '1.2.3.4') # will set a new address """ def __init__(self, idx=1, name=None): self.skt = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, 0) fcntl.fcntl(self.skt, fcntl.F_SETFD, fcntl.fcntl(self.skt, fcntl.F_GETFD) | fcntl.FD_CLOEXEC) self._index = idx self._name = name # Get the name of the interface if (self._name == None): self._name = self.name else: self._name = (c_ubyte*IFNAMSIZ) (*bytearray(self._name)) self._index = self.index def __newIfreqWithName(self): ifr = ifreq() ifr.ifr_name = self._name return ifr def __doIoctl(self, ifr, SIOC, mutate = True): try: fcntl.ioctl(self.skt, SIOC, ifr, mutate) except IOError as ioException: if ioException.errno == 99: pass else: raise ioException def __getSimple(self, ioctl, elem): ifr = self.__newIfreqWithName() self.__doIoctl(ifr, ioctl) elem = elem.split('.') tmpVal = ifr for curElem in elem: tmpVal = getattr(tmpVal, curElem) return tmpVal def __setSimple(self,ioctl, elem, val): ifr = self.__newIfreqWithName() elem = elem.split('.') tmpVal = ifr for curElem in elem[:-1]: tmpVal = getattr(tmpVal, curElem) setattr(tmpVal, elem[-1], val) self.__doIoctl(ifr, ioctl) @property def index(self): ifr = self.__newIfreqWithName() self.__doIoctl(ifr, SIOCGIFINDEX) self._index = ifr.data.ifr_ifindex return self._index @property def name(self): ifr = ifreq() ifr.data.ifr_ifindex = self._index self.__doIoctl(ifr, SIOCGIFNAME) self._name = ifr.ifr_name return string_at(self._name) @name.setter def name(self, val): ifr = ifreq() ifr.ifr_name = self._name ifr.data.ifr_newname = val self.__doIoctl(ifr, SIOCGIFNAME) self._name = val @property def flags(self): return self.__getSimple(SIOCGIFFLAGS, 'data.ifr_flags') @flags.setter def flags(self, val): self.__setSimple(SIOCSIFFLAGS, 'data.ifr_flags', val) @property def ifqlen(self): return self.__getSimple(SIOCGIFTXQLEN, 'data.ifr_ifqlen') @ifqlen.setter def ifqlen(self, val): self.__setSimple(SIOCSIFTXQLEN, 'data.ifr_ifqlen', val) @property def metric(self): return self.__getSimple(SIOCGIFMETRIC, 'data.ifr_metric') @metric.setter def metric(self, val): self.__getSimple(SIOCSIFMETRIC, 'data.ifr_metric', val) @property def mtu(self): return self.__getSimple(SIOCGIFMTU, 'data.ifr_mtu') @mtu.setter def mtu(self, val): self.__getSimple(SIOCSIFMTU, 'data.ifr_mtu', val) @property def hwaddr(self): ifr = self.__newIfreqWithName() self.__doIoctl(ifr, SIOCGIFHWADDR) hw = ifr.data.ifr_hwaddr.gen.sa_data self._hwaddr = '' for i in hw[:IFHWADDRLEN] : self._hwaddr = self._hwaddr + '%.2X:' % i return self._hwaddr @hwaddr.setter def hwaddr(self, val): ifr = self.__newIfreqWithName() ifr.data.ifr_hwaddr.sin_addr.s_addr = val self.__doIoctl(ifr, SIOCSIFHWADDR) @property def addr(self): ifr = self.__newIfreqWithName() self.__doIoctl(ifr, SIOCGIFADDR) return ifr.data.ifr_addr @addr.setter def addr(self, val): ifr = self.__newIfreqWithName() ifr.data.ifr_addr = self.__sockaddrFromTuple(val) self.__doIoctl(ifr, SIOCSIFADDR, False) @property def broadaddr(self): ifr = self.__newIfreqWithName() self.__doIoctl(ifr, SIOCGIFBRDADDR) return ifr.data.ifr_broadaddr @broadaddr.setter def broadaddr(self, val): ifr = self.__newIfreqWithName() ifr.data.ifr_broadaddr = self.__sockaddrFromTuple(val) self.__doIoctl(ifr, SIOCSIFBRDADDR) @property def netmask(self): ifr = self.__newIfreqWithName() self.__doIoctl(ifr, SIOCGIFNETMASK) return ifr.data.ifr_netmask @netmask.setter def netmask(self, val): ifr = self.__newIfreqWithName() ifr.data.ifr_netmask = self.__sockaddrFromTuple(val) self.__doIoctl(ifr, SIOCSIFNETMASK, False) def __getSinAddr(self, sockaddr): if sockaddr.gen.sa_family == socket.AF_INET: return sockaddr.in4.sin_addr.s_addr if sockaddr.gen.sa_family == socket.AF_INET6: return sockaddr.in6.sin6_addr.in6_u return 0 def __sockaddrFromTuple(self, inVal): if inVal[0] == socket.AF_INET: sin4 = sockaddr() sin4.in4.sin_family = inVal[0] sin4.in4.sin_addr.s_addr = struct.unpack('<L', socket.inet_pton( inVal[0], inVal[1]))[0] return sin4 elif inVal[0] == socket.AF_INET6: sin6 = sockaddr() sin6.in6.sin6_family = inVal[0] sin6.in6.sin6_addr.in6_u = hexlify(socket.inet_pton( inVal[0], inVal[1])) return sin6 raise "Input must be tuple like (AF_INET, '127.0.0.1')" def __sockaddrToStr(self, sockaddr): if sockaddr.gen.sa_family == 0: return 'None' p = struct.pack('<L',self.__getSinAddr(sockaddr)) return socket.inet_ntop(sockaddr.gen.sa_family, p) def __str__(self): x = '' x = x + 'Iface: %s Index: %d HWAddr: %s\n' % ( self.name, self._index, self.hwaddr ) x = x + 'Addr:%s Bcast:%s Mask:%s\n' % ( self.__sockaddrToStr(self.addr), self.__sockaddrToStr(self.broadaddr), self.__sockaddrToStr(self.netmask) ) x = x + 'MTU: %d Metric: %d Txqueuelen: %d\n' % ( self.mtu, self.metric + 1, self.ifqlen) x = x + 'Flags:\n%s' % flagsToStr(self.flags) return x def getIfaces(): """ Returns a list of all available interfaces. """ ret = [] i = 1 while True: try: ifa = Interface(idx=i) ret.append(ifa) i = i+1 except: return ret if __name__ == '__main__': print 'All your interfaces' allIfaces = getIfaces() for iface in allIfaces: print iface iff = Interface(name='eth0') iff.flags = iff.flags & ~IFF_UP print iff iff.flags = iff.flags | IFF_UP | IFF_RUNNING iff.addr = (socket.AF_INET, sys.argv[1]) print iff iff.netmask = (socket.AF_INET, sys.argv[2]) iff.flags = iff.flags | IFF_UP print iff iff.flags = iff.flags & ~IFF_UP print iff
I wrapped this code in a package and named it pyiface. Available to you now here: https://github.com/bat-serjo/PyIface
Soon I will make this package available as PyPI.
Friday, June 22, 2007
Burglars cops treasures and python, this time we got it all.
So we got these burglars who have this map that shows where the treasures are. Hmmm right, this is clear. Then we got these cops that want to stop the burglars. Now the map looks something like this.
4 3 3 3
3 -1 2
-1 -1 -1
3 12 7
The first row contains some stupid numbers showing different things, because the solution of this problem is supposed to be written in C, but hey fuck C and it's stupid libraries ( this from a guy who makes a living like a professional C programmer - me ) The most important number from the first row is the second one which shows the time ticks the burglars have before the cops show up. The rest of the numbers say what's the array height and width (useless in python and in fact in C if you take the time to code is right).
Now the rules are simple. The burglars have the map so they know where the treasures are. Each treasure is represented by a positive number showing the amount of money the gain when they reach it. The cells with negative numbers does not contain treasures and they cost money to be dug. Each cell is dug for one tick time. The cops will come in K ticks of time where K is the second number in the first row. In order to get to a cell the burglars must dug out all the cell in it's column prior to it. The burglars may start from any column and stop digging within the column whenever they want.
Make a program that finds the maximum amount of money the burglars can gain without being caught from the cops.
He he, me lazy so code in python.
Now test it!
serj@tokamak ~> cat input
4 3 3 3
3 -1 2
-1 -1 -1
3 12 7
serj@tokamak ~> ./stamen.py
10
Now test it again.
serj@tokamak ~> cat input; ./stamen.py
4 3 3 3
3 -1 24
-1 -1 -1
3 12 7
30
Yes it wErks! :-D
4 3 3 3
3 -1 2
-1 -1 -1
3 12 7
The first row contains some stupid numbers showing different things, because the solution of this problem is supposed to be written in C, but hey fuck C and it's stupid libraries ( this from a guy who makes a living like a professional C programmer - me ) The most important number from the first row is the second one which shows the time ticks the burglars have before the cops show up. The rest of the numbers say what's the array height and width (useless in python and in fact in C if you take the time to code is right).
Now the rules are simple. The burglars have the map so they know where the treasures are. Each treasure is represented by a positive number showing the amount of money the gain when they reach it. The cells with negative numbers does not contain treasures and they cost money to be dug. Each cell is dug for one tick time. The cops will come in K ticks of time where K is the second number in the first row. In order to get to a cell the burglars must dug out all the cell in it's column prior to it. The burglars may start from any column and stop digging within the column whenever they want.
Make a program that finds the maximum amount of money the burglars can gain without being caught from the cops.
He he, me lazy so code in python.
#!/usr/bin/env python
import os, sys
K = 0 # edinici vreme, broi kletki koito mogat da izkopaqt
def GetData(file=''):
f = open(file, 'r')
data = f.readlines()
f.close()
params = []
for i in data[0].split():
params.append(int(i))
data = data[1:data.__len__()]
array = []
for d in data:
array.append(d.split())
return (params, array)
class PreData:
def __init__(self, t=0, m=0):
self.time = t
self.money = m
def __repr__(self):
return 'Time: '+str(self.time)+' Money: '+str(self.money)
def __str__(self):
return 'Time: '+str(self.time)+' Money: '+str(self.money)
def GetPreData():
columns = []
tmpK = 0
tmpAward = 0
r = 0
c = 0
global K
((N,K,L,D), data) = GetData('input')
for c in xrange(0, L):
treasures = []
tmpC = PreData(0,0)
for r in xrange(0, D):
tmpC.time = tmpC.time + 1
tmpC.money = tmpC.money + int(data[r][c])
if int(data[r][c]) > 0:
if tmpC.time > int(K):
break
if tmpC.money > 0:
treasures.append(PreData(tmpC.time, tmpC.money))
tmpC.time = 0
tmpC.money = 0
columns.append(treasures)
return columns
maxMoney=0
def Recursion(cols=[], c=0, r=0, money=0, time=0):
global maxMoney
if c >= cols.__len__():
return
if r >= cols[c].__len__():
return
if (cols[c][r].time+time) > K:
return
cmoney = money + cols[c][r].money
ctime = time + cols[c][r].time
if maxMoney < cmoney:
maxMoney = cmoney
Recursion(cols, c + 1, r, cmoney , ctime )
Recursion(cols, c, r + 1, cmoney , ctime )
cols = GetPreData()
for i in range(0, cols.__len__()):
Recursion(cols, i, 0, 0, 0)
print maxMoney
Now test it!
serj@tokamak ~> cat input
4 3 3 3
3 -1 2
-1 -1 -1
3 12 7
serj@tokamak ~> ./stamen.py
10
Now test it again.
serj@tokamak ~> cat input; ./stamen.py
4 3 3 3
3 -1 24
-1 -1 -1
3 12 7
30
Yes it wErks! :-D
Subscribe to:
Posts (Atom)