Tuesday, January 25, 2011

Notes from 27th Chaos Communication Congress - day 2

Here are some notes from the second day of the 27th Chaos Communication Congress. See also
day 1, day 3, day 4.

Lightning talks - day 2



  • Data Privacy Management: http://www.daprim.de/
  • Starfish: http://www.kemenczy.at/ "Fully distributed, user-controlled
    network": Not a network of star topologies, each node has redundant links;
    no centralized authority.
  • FreedomBox: http://wiki.debian.org/FreedomBox
    An alternative to closed clouds: privacy control, decentralization,
    personal information stored at home.
  • Arduino: "An easy way to get into microcontrollers, for non-geeks"
  • Telecomix DNS: http://gitorious.org/telecomix-dns
    A decentralized DNS server network, an alternative to ICANN: reliability,
    stopping domain seizures.
  • SAP insanity: General complaints about the product: On-screen keyboard
    only. Column mapping GUI between tables only with arrows, with hundreds of
    attributes results in a mishmash of lines.
  • SMS port scan: Set up a SMS interface to a port scanner, running on the CCC GSM
    network.
  • TSAscreening: http://bit.ly/tsarights
    "You are next", "they're the ones being terrorists".
    By law, search can be only only reasonable and necessary; you have right to record on a camera; you have right to bring medical liquids (juice!).
  • NetS-X: http://code.google.com/p/nets-x/
    "A hacking game" = e-learning on net security, sandboxes for playing


I Control Your Code


The idea is to use separate identities/rights for each (user, application)
pair.

The "proposal" is "user-space virtualization" to authorize all syscalls: use
binary translation of all code, prevent:

  • control flow transfers to unexpected code (only to .text areas, only to known functions in inter-module transfers)
  • unexpected returns/indirect jumps (only to valid targets, shadow all stack)
  • jumps into middle of instruction
  • switching between 32-bit and 64-bit code

Therefore, all instructions are guaranteed to be validated, so we can have a
policy authorizing system calls.

Also can be used to track "unmodified" execution.

Implementation: http://nebelwelt.net/projects/fastbt/ - 6-8% overhead

Policy strength / comparison with SELinux: Can enforce a list of allowed
syscalls + arguments, has also a learning mode. Can add specific checks
(by writing code).

Comparison with HW virtualization: overhead 3-5%, but it's not possible to
get instruction-level control.

SSL Observatory


http://www.eff.org/observatory

SSL problems: Too many trusted parties; CA bugs allowed e.g. the \0 attack.
We should be afraid of X.509 - too flexible, ugly, history of implementation
vulnerabilities.

EFF SSL observatory: contacted all allocated IPv4 addresses. 16.2M IP addresses listening, 11.3M started SSL, 4.3M used valid certs
(1.5M distinct valid leaf certs)

Found 1482 trustable CAs (incl. intermediate CAs)! - 1167 issuer strings, 651
organizations (~200 are German universities through a single intermediate).
Notable cases: dept. of homeland security, US defense contractors, CNNIC
(China - root CA controversy is really irrelevant), Etisalat (Dubai -
installed malware on customer's hardware), Gemini observatory

~30k servers still have Debian broken keys (out of which ~500 had valid CA
signatures)

There is no general way to contact a CA (e.g. to ask them to revoke a cert).

Weirdness found: certs that both are and aren't CAs, certs for "localhost",
127.0.0.1.

Firefox and IE cache intermediate CAs, so we can't say for sure if a cert is
valid - it may be valid only if the user has "validated" the CA by visiting a
different site where the CA was signed; there are 97K such certificates.

EV certificates: Identified by (CA-specific) OID. Don't work all that well
with browser Same Origin Policy - EV to non-EV references considered "same
origin". Problems found: RFC-1918 addresses, unqualified names, weak keys,
long expirations. 13 issuers violated EV spec by signing a weak key (even a
512-bit key!) Found EV certs with wildcards, also violate policy.

Data is available for download.

Plan for a decentralized SSL observatory, code in progress. Design: use Tor
to send observed raw certs - may get a reply notifying about a MITM; this
only works with a delay, but better than nothing.

DNSSec: no longer sure about it being a good thing, due to recent domain
seizures by US.

High-speed high-security cryptography (DJB)


I'm not summarizing this- go read
the slides! Relevant, inspiring, perhaps not quite practical as presented.

Data recovery techniques


The process goes through all layers of the mechanism: data acquisition
(complete or partially destroyed), disk array composition, iSCSI/NAS data
layout handling (iSCSI disk is a file, optionally fragmented), handling
virtualization, file systems, file formats (e.g. a database), verification of
the result (is the data valid?).

HW lab setup: Clean atmosphere necessary - "most of dust comes from
customer's drive". Stereo/video microscopes used for observing head
alignment. "Buy the best tools" - "no tools are better than bad tools".
Disks needed both for making a 1-1 copy to physical disk, and as spare
parts - there are ~10K drive models on the market; sometimes spare parts
don't match even on the same model # (manufacturer fulfills contract to ship
legacy models by shipping new model with firmware-limited capacity).

Tool examples: flash chip reader, "head lifter" (custom), a tool to extract
the platter out of the bearing, a press to put the platter onto a spindle.

Data acquisition from a disk: spinning the disk - in its shell or a replaced
shell; can't get data without spinning the drive in <1 month => impractical.
Used to use a "spin stand" - today it is almost impossible to align the
platter correctly. As a last resort: magnetic microscope - can handle broken
platters, but reading a single surface takes ~5 years.

Data acquisition from flash: PCB damage: can be fixed, but rare; otherwise
desolder chip, read it, reorder blocks.

Kinds of damage for disks: surface damage; bent spindle (=> stuck); defective
heads (stuck to surface); electronic failures; firmware corruption; media
contamination (e.g. bearing fluid); fire; water. Hard drives are not
sealed/devacuated - there are little holes to even out pressure, so water can
get in. Fire damage is normally not hot enough to damage magnetic data. For
flash it is about the same, except for physical damage.

Drive heads: with >1 head, only 1 activated/pre-amplified at a time. Some
firmware just fails, if other head is on an unexpected position => need to
align heads correctly to each other.

Validating recorded files: replace unread blocks with a pattern (which
includes some metadata) => can check if a recovered file has been damaged,
can focus on priority missing data.

Fun with firmware: There is a separate HW connector - on Seagate serial I/O,
3.3V, only starts talking after Ctrl-Z. HD commands are family-specific.

Best way to kill a drive for sure: "really difficult". In most cases
overwriting data 1x is OK - overwriting multiple times doesn't help. LBA and
physical addresses aren't 1-1, so one never knows if the data was actually
overwritten.

HW firmware implementation: standard CPUs, ARM is popular. Reverse
engineering: the firmware contains several megabytes of code and data, most
firmware is actually loaded from the media!

Backdooring embedded controllers:


Exitsting laptop backdoors: hardware (keyloggers etc.), software (OS), BIOS,
ACPI; Firmware, other devices - will ONLY cover the EC here.

EC = Embedded Controller: 8- or 16-bit MCU, "beefed up 8042 keyboard
controller", "Renases" on ThinkPads. Controls sensors, actuators
(temperature, battery, fans, brightness, LEDs). Handles hotkeys (VGA output,
brightness control) => needs key press data. (MacBook has an USB keyboard =>
different architecture).

Focus: ThinkPad's "Renases": Based on H8S, running when laptop has power
(even when "off"). BIOS and EC can be flashed via LAN! Some laptops have it
enabled by default!

Easy to work with: Commented disassembly for T43 already exists:
ec.gnost.info/ec-18s/ The author of the patch to swap Fn and Ctrl allegedly
never had Lenovo hardware.

The implemented backdoor can record and provide keystroke data - 4kB space
available, 5:1 compression => 20K keystrokes. To get data out, can use ACPI
results, or use a LED wire as an antenna. To send data remotely: can use a
covert timing channel (manipulating keystroke timing).

Defense: Dump EC firmware (reliable - implemented through HW, malicious
firmware can not tamper), then we can verify it. Plan to use
coderpunks.org/ecdumper to see if it is a known version (but what about
trust, i.e. an attacker submitting a hacked version?).

Future plans: Examine other reflashable devices. "Would like to see" vendors
signing firmware, verifying it on boot (TPM enabled probably can't
[currently] detect this). We need "fundamental discussion" about firmware
trust.

Dumping firmware is done via a protocol over ports 60/61. The original
firmware was found in a DOS version of BIOS updates, *.FLZ contains both BIOS
and EC firmware. Tools used: GNU binutils, a checksum
recomputation tool.

Tuesday, December 28, 2010

Notes from 27th Chaos Communication Congress - day 1

Here are some notes from the first day of the 27th Chaos Communication Congress. See also
day 2, day 3, day 4.

Keynote

5 years ago speaker said at CCC "we have lost the war": a perfect storm:
post-9/11 paranoia, EU data retention, climate change. As of today, war not
actually lost: German constitutional court started protecting privacy
- OTOH Netherlands has a constitution, but not a court, so the majority can
ignore constitution => fearmongering and other aspects of usual politics;
Netherlands has now become an cautionary tale WRT privacy.

Political recommendations: watch party funding, "literally by all means
defend the constitution".

Speaker "mildly bipolar", was recommended anti-depressants - "being unhappy
has become socially unacceptable". If depression is a force that pushes us
to make painful but necessary changes, antidepressants prevent necessary
change - perhaps there might be a political-pharmaceutical complex one day?

Success on voting machines: Illegal in both Germany and Netherlands (Germany
"safe" - constitutional court, in Netherlands will need to fight this war
over and over again with each single mayor) E-voting in Brazil: black box,
gets an ID card from each voter - future versions will event collect a
fingerprint.

Wikileaks: Speaker did not participate in the latest release, "possible
ramifications scared the bejezus out of me", "I can't live from a backpack".
Important, but outcome is uncertain: "Not sure what has been unleashed" -
attacks on Internet freedom will certainly increase. US proposes to be able
to get plaintext from any service - "Crypto war 2.0 starting". "Anonymous is
getting on my nerves" - "real hackers would not release real names in PDF
metadata", lacking a "level of maturity" - "we" [at CCC] might attack, but
nothing good comes out of it.

Politicians don't know what's going on, can't control it, can only pretend
they are in control for the voters. "Hackers don't have the answers", but
understand the dangers of complexity - "lack of slack"; "CCC does not cause
chaos - we have prevented some aspects, and we understand chaos a little".

Living in a world of separate viewpoints/narratives, from "Apple, Google,
Facebook and the geographically-challenged traditional governments"

Future: Basic story remains - we lost the war. "It's going to be a mess":
"difficult times, not end times" - build trust relationships, diverse skill
sets, be flexible.

CCC logistics: too many of us, need to move out to be able to attract new
people. DEFCON given as a counterexample for expansion, probably does not
apply here - CCC never had their problems..

Code deobfuscation by optimization


http://code.google.com/p/optimice/

An IDA plugin to decode/simplify semantics on an obfuscated code, optionally
"assemble" into a new code segment for further processing in IDA.

Handling obfuscation: Small basic blocks, "push+return" to break IDA graphing
are simplified/converted. Fake paths (conditional jumps to nonsensical
bytes) are simplified. Overlapping instructions are duplicated.

Implementation: Build a CFG. For instruction semantics, use "MazeGen's XML
at ref.x86asm.net" to track all inputs/outputs. Optimizations performed: JMP
threading, conditional jump simplification, dead code removal, various
heuristics, e.g. push+ret->jmp. Constant propagation/folding unimplemented.

Contemporary Profiling of Web Users


Research on defeating web proxies / anonymizers / Tor. etc. "In private
communication research, dummy traffic was researched in the last 20 years and
has never been a solution"

Proxies that remove JavaScript:


We want to limit JS: it can e.g. get screen size, local date (=>clock offset
and drift). Existing proxy projects are dead.

The proxies 1) remove <script> 2) move content out of <noscript>, both using
regular expressions. PHProxy attack: <noscript><scr</noscript>ipt> .
Glype: same attack on <object> . Also, Java can load JS as well:
...showDocument(..."javascript:..."...) .

When JavaScript is enabled, but filtered: When DOM modification are used to
hide objects, it is usually possible access the originals. NoScript can
forbid 3rd party JS for tracking, but code can still load 3rd party CSS.
Another specific problem is filtering <object archive=...>, but not
<object><param name=archive .../> .

Identifying users by web profile


Assuming an anonymizer, or watching users on a DNS server. Identifying the
user is easy with static IP; dynamic IP "should" protect (changing IP
address on DSL, or Tor changing the routing each 10 minutes).

Using standard machine learning using mechanisms for word frequencies to
learn on host access frequencies, using a "multinomial naive Bayes
classifier". In experiment, successfully identified 77% of "links" (user on
day D => user on day D+1). Accuracy is good even with 10-minute sessions
(i.e Tor). Longer time between learning and classification doesn't hurt
much.

Recommendations: Change IP address frequently and do not continue previous
activities after the change. Use _separate_ proxies for each activity.
Randomly distributing activity across multiple proxies does not help - each
proxy has similar data. Visiting only popular pages does not help much.

Detection of bots and other strange users



Motivation: heavy load by bots, proprietary databases crawled by
competitors.

  • If load balancing: make it deterministic (e.g. md5 of client's IP), look
    for "incorrectly" connecting users. This is trivial, but actually works -
    many bots are lazy and just connect to host 0.
  • Observe behavior: client that does not access images/JS, connects too often.
  • User-Agent: Fake user agents are often too old (IE 5.5). HTTP header
    characteristics (order/capitalization) allow quite specific user-agent
    detection, allow detection of faked User-Agents. These techniques are
    both easier to do "after" load balancing proxies because the proxies will
    defragment the input, making evasion more difficult.

    Local attacks on Tor


    "Local" = connection between client and Tor entry node. Attempting web site
    fingerprinting using traffic analysis only (timing, packet sizes), want to
    see if a specified site was visited. Timing information is mostly useless
    due to Tor's load and circuit changes; Tor "should" protect against size
    fingerprinting dues to fixed-size cells.

    Machine learning again: Need to train this with each browser separately, and
    extract separate requests (not mixed with unrelated sites). Using
    "Multinomial naive Bayes", "Support Vector Matrices", training on packet
    sizes and direction, "ignoring ACKs" = counting the total size of a transfer
    in one direction until the direction changes.

    Detection accuracy when training against "all possible sites" is >95% on
    OpenSSH,OpenVPN, IPec. Tor started with 3%, can now get 55% => feasible.
    "Jap": interestingly the problem is more
    difficult on the free version than on the premium one.

    Detection when distinguishing between a few "interesting" sites and "rest of
    Internet": training with a representative sample for "rest". With 5
    "interesting" sites need ~2000 samples for <1% false positives, will get
    67% false negatives.

    Recommendations: Do multiple things at the same time (tabs, Internet
    radio...) - decreases success to ~10%.

    Automatic identification of crypto primitives in software


    http://code.google.com/p/kerckhoffs/

    A master thesis, limitations: Assumes no obfuscation, no JIT/interpretation,
    only limited to crypto (nothing else, and not block cipher mode).

    Existing tools: signature based, or dynamic instrumentation measuring
    percentage of "bitwise" operations (globally / in a basis block / function),
    looking for loops that change entropy

    Implementation: Intel's PIN for dynamic instrumentation to get insn-level
    execution trace. Then reconstructs CFG ("dynamic" = including indirect
    jumps), jump taken/not taken statistics, detects loops, memory ranges/areas.

    Algorithm identification methods:

    • Excessive use of bitwise instructions.
    • Sequences of (instruction mnemonics, constant operand) pairs, find fingerprints - e.g. combinations unique for an implementation.
    • Loops (X often unrolled): observe (number of executions of the loop as a whole, number of iterations, number of instructions in a loop).
    • Look for a specific relation (e.g. AES (input, key, output)) between blocks of data with a suitable size


    libUSB


    A generic introduction to USB - releases, limitations, transfer types, endpoints, descriptors, usage of libusb on various OSs.

    Desktop on Linux


    From a PoV of an UNIX sysadmin... It seems difficult to keep up with the
    technology changes. Presentation overshadowed with explanations by Lennart
    Poettering.

    Distributions focusing on "Dumbest Assumable User", few sysadmin controls
    available/visible.

    MM frameworks: too many layers (=> loses relevant information on the way with
    Phonon+GStreamer+PulseAudio). GStreamer backend to Phonon unmaintained,
    still used by default in "some distributions"

    GDM: complicated - why do we need a full GNOME session? (Answer: a11y pulls
    audio, which pulls bluetooth, ...; g-p-m necessary for default power
    policy). GDM doesn't handle systems with many users well; Can't show all 3.5k
    names in any case. When that is disabled, still shows recent users and
    "Other" - users mistake login screen for a screen lock.

    ConsoleKit: Sorry state of documentation: "Defining the problem: To be
    written" after all these years. Intended to manage separate seats, but ACL
    changes illusory without revoke(). Not robust - changes persistently-stored
    ACLs but keeps only in-process state => ConsoleKit crash leaves around
    obsolete ACLs.

    D-Bus complaits: Nonsensical name spacing ("you need a domain", "narcissistic
    naming: based on project name, doesn't tell what it actually does). Would
    like implementation-independent interfaces [X where to get the
    implementations?]. TCP transport: "no authentication, no authorization, no
    encryption". (Lennart: ['we' agreed that] "D-Bus won't be used across the
    network full stop")

    IPv6


    Many "old" vulnerabilities were carried forward from IPv4, previously
    presented:

    • Neighbor discovery spoofing <-> ARP spoofing
    • Duplicate address detection DoS [answer "this is a duplicate" to everything]
    • Rogue autoconfiguration server <-> rogue DHCP server


    Routerless networks: Sending a router advertisement with 0 lifetime "kills"
    the router for clients. Per RFCs clients treat any address as _link-local_
    if no router exists.

    Unexpected RA on an IPv4-only network: switches on dual stacks. Thus we can
    bypass IPv4-only firewalls, can MITM on IPv6 because IPv6 transport is
    preferred to IPv4.

    RA flooding: 1m bogus RAs DoSes Cisco, Windows, old Linux (100% cpu).

    Remote ping scans: Originally thought infeasible due to large address space,
    broadcast doesn't exist. But we can still use search engines, DNS, common
    addresses. Randomly chose 17k DNS names. The following "host address" (= host part
    within network) sources exist:

    • Autoconfiguration: either link-local = based on MAC (can guess if you know
      the (company standard) manufacturer), or "Privacy option" = random and
      changing from time to time
    • DHCP: allocated sequentially! => "if you got one, you got all"; common
      ranges based on example documentation
    • Manually configured: ::1, ::2, ..., or ::service_port, IPv4 address, and
      simple variants of these.

    Overall, can easily guess ~70% of host addresses. A scan only needs to try
    ~2100 host addresses (1-20 seconds) to get 70-80% of hosts, similarly try
    ~1500 common host names. A scan may return a router's "not available"
    message for a different network, giving us more targets. We can iterate
    between guessing hosts on a network, and using reverse DNS to get more
    starting points. Altogether we can identify~90-95% of servers (not counting
    other kinds of hosts).


    Multicast DoS: Multicast background: A "query" router periodically prompts
    for confirmation of existence of multicast receivers. We can spoof
    "unsubscribing" message, but this will cause another prompt and resumption of
    traffic. If we become the "query" router, we can avoid sending the prompt.
    "Query" is voted by local link address => 0000000 wins [nobody configures a
    router on 0]. Then we can unsubscribe the network, except that other routers
    would assume the router is dead if no prompts were seen. To avoid this, send
    the prompts - but only to a "router-only" multicast MAC.

    To see if a Windows/Linux computer is sniffing the network: Send a packet
    (ping) to an _unused_ multicast address, see if the host responds.

    Side channels in IPv6: "IPv6 is a side channel" - too much functionality,
    cannot be reasonably filtered

    Code available at http://www.mh-sec.de/downloads/thc-ipv6-1.4.tar.gz .
    Will start www.ipv6{security,hacking}.info for secure configuration advice.

    Mitigations:

    • ACLs on L3 switch (e.g. don't allow RAs from client ports), if supported
    • IPSec, but a pain
    • Secure Encrypted neighbor Discovery - basically happening in the switches,
      not supported yet anywhere, still has problems.
    • More secure client configuration - not always possible
    • Detection of attacks is easy, prevention unknown

      Analyzing Stuxnet


      Presented by Microsoft "to set the facts straight". Analyzed within a few
      weeks after this came in, but not allowed to talk about it at the time.
      2 interesting things: _4_ 0-day vulnerabilities, attack on SCADA.

      Discovered: by VirusBlokAda (Belarus, not known by Microsoft) sent a sample
      in ~July, eventually got the original LNK files. Others are looking at this
      as well - need to "know ahead" about threats, ~1 MB of binary; full knowledge
      sharing with Kaspersky.

      Methodology: "initial triage" - identify surprising code, clues for
      vulnerabilities, then discuss details with developers of relevant code.
      Total time ~30-40 man-hours in 3-4 days to find the vulnerabilities. Later
      completely decompiled 2 components to buildable C.

      Attackers: "Don't ask me who the author was". Components were written by
      different people. Aiming for 100% reliability, high impact. Developed on
      removable media (path embedded in file is B:...). Shell code does not use
      simple "call" insns - always "ret".

      Attack 1: LNK files


      Dumped LNK as text, identified the buggy DLL; all done in ~1 hour. Bug:
      .CPL has icons inside => must do LoadLibrary(), which calls DllMain(). Fix:
      limit icon loading to only registered .CPLs.

      Impact: Arbitrary code execution without privilege escalation - only a
      foothold for further attacks. Looked at attack vectors - in addition to
      USB, could use WebDAV (remote attack) => fixed it "out of band",
      "telemetry" told them users were being affected. 100% reliable attack
      vector. Apparently some people knew about this for years.

      Attack 2: Task scheduler


      Debugging was not really helpful => using process monitor, event logs -
      noticed that task files were accessed. Bug: XML file storing task data
      (including the user to run it as => can escalate to LocalSystem) _writable
      by user_, authenticated using a CRC32 hash (which was protected against user
      access); CRC32 collisions are easy. Fix: use SHA256 (kept files writable
      "for compatibility" [with what??? the authentication would break writing
      anyway])

      100% reliable - but only works on >= Vista.

      Attack 3: Keyboard Layout


      Eventually found "not immediately obvious" code - searching in win32k.sys,
      NtVirtualAllocateMem, keyboard layout loading, some IDA-unidentified code.
      Tried various things, finally noticed the code looks like a shell code and
      inserted a break point in it to get a back trace. Bug: <=XP allowed loading
      keyboard layouts from any directory, indexed a function array using an
      unvalidated user-controlled integer. Attack looked for a suitable user-land
      address following the original table, copied attack code there.

      100% reliable - only <= XP, so we can assume the attacked environment is
      not monolithic.

      Attack 4: Printer spooler


      Kaspersky reported suspicious spooler RPC. Network trace: guest printing to
      files in %system%. Spooler should have switched to the client account, but
      it doesn't for Guest because it is too limited, so it uses System instead.
      Windows by design automatically runs a .MOF file dropped in there :)

      This all only works if anonymous connections are allowed, which is very
      uncommon in corporations

Sunday, May 2, 2010

Groovy Recipes

Groovy Recipes: Greasing the Wheels of Java, from the Pragmatic Programmers series, is really two books in one: First, it is what it promises: a collection of practical, easy to reuse code for common tasks.

Second, when read sequentially, it is a good tutorial to the language. Sometimes there are two or three "recipes" that really build an interface around some common piece of code, and each of the recipes dutifully repeats the explanation of the common code. This happens only in the latter parts of the book, when the job of explaining the language proper is done, so it is easy to forgive.

As for Groovy the language, the light-weight syntax and automatic hiding of getter/setter methods is a very welcome improvement over Java; for me, the availability of closures alone is a good enough reason to prefer Groovy to Java. When viewed as a "better Java" (as opposed to viewing it as a completely separate language), Groovy does suffer from the ".NET disease", extending the language too far outside of the "philosophy" of the language into areas that should be in libraries or omitted completely, e.g. the way every "delegate" in .NET can automatically call more than one function. (This disease is by no means restricted to .NET - see e.g. <tgmath.h> in C, or enum and other recent-ish additions to Java.) In Groovy, the methodMissing feature and the ability to add methods to a class at run time seems to me far too different from the original Java object model.

If you have used Java before and turned away with sore fingers and disgust, do look at Groovy; it may not be good enough to become your primary language, but it will make cooperation with Java software much more bearable. If only someone replaced the endless XML "configuration" in .war, .ear etc. archives by something usable...

Saturday, October 17, 2009

Zkušenost s duchodovepojisteni.cz: nebrat!

Kdybyste jako já hledali relativně výhodného agenta pro penzijní připojištění, jděte někam jinam.

Uzavření penzijního připojištění na http://duchodovepripojisteni.cz/ (Jupiter Praha s.r.o.) tehdy fungovalo v pořádku. Posledního čtvrt roku ale byl na infolince jen záznamník, e-mailový kontakt je přesměrovaný na neexistující doménu, jednatel společnosti (podle adresy z whois) také nereaguje.

Na inzerovaných 110% měsíčního příspěvku můžete samozřejmě zapomenout—kromě výše uvedeného také proto, že účetní závěrka v obchodním rejstříku uvádí k 31. 12. 2008 závazky po splatnosti ve výši 197 tisíc Kč.

Zkrátka, nebrat...

Thursday, October 1, 2009

Power of story telling: Test-driven Development by Example

I generally prefer reference books to introductory tests, so when I got the opportunity to read Kent Beck's Test Driven Development By Example, I was really surprised how easy to read—dare I say fun?—it was. It seems human brain is really set up to handle stories better than pure facts, and to enjoy them more—the book propels the reader through the text in no time, using the "what's happening next?" feeling usually experienced only when reading fiction.

Taken from a very high level, most of the book is unsurprising: the basic idea of test-driven development can be explained in roughly five sentences, and the rest of the book follows naturally. The book does show quite a few techniques and tips on using the test-driven methodology, and it's useful to read them all in one place, although most programmers would eventually discover most of them independently—but did I mention reading the book was fun?

The third part of the book, titled "Patterns for Test-Driven Development", deviates from the "telling a story" format, and the difference is quite noticeable. Although the section is still interesting and useful, it tends a bit closer to the "patterns are so important the text must be repetitive and boring" style (of which The Gang of Four book is an instructive example) than I'd like. One particular section, which describes a very nice way to replace an internal data representation without breaking anything (this single section is a good enough reason for me to recommend the book!), contains two five-step recipes in a "How" subsection, and a detailed description in the "Why" subsection. The immediately following sections use the same "How"/"Why" pattern, in most cases unnecessarily—culminating with a completely ridiculous "How do you add a parameter to a method?" three-step program. Fortunately the "How"/"Why" pattern is gone in the next chapter.

I really missed a larger-scale example in the book; the examples provided very rarely contained a method longer than 10 lines, with roughly 3 lines being the average method size. Splitting a real-world program in so many small pieces of code seems to me rather impractical—it requires introducing too many helper objects to hold variables, and holding too many additional concepts (e.g. method names, object relationships) in one's head at a time to be able to think about the overall algorithm spanning perhaps 100 or 200 lines. A larger-scale example that demonstrated how real-world code written using the test-driven development methodology could look like would be quite useful to evaluate the methodology in other terms than achieving outstanding test code coverage.

In any case, the book is interesting and fun to read - even if you "never have time to write tests", don't hesitate to read it if you get the opportunity.