Tuesday, October 2, 2012

Seven Languages in Seven Weeks - Scala Day 2 Self Study

Hey there! I'm currently reading Seven Languages in Seven Weeks by Bruce A. Tate. As the title implies, this book explores seven different programming languages. Each chapter ends with a self study section. Here are the exercises of day 2 with the Scala programming language:

Use foldLeft to compute the total size of a list of strings:
Here are two variants, the first calls the foldLeft method (note the multiple parameter list, this is used for currying, i.e. partial function application) while the second is using the /: infix operator, which is in fact an overload of foldLeft:
  val list = List("foo", "bar", "hello", "world")
  list.foldLeft(0)((len, elem) => elem.size + len)//> res0: Int = 16
  (0 /: list) {(len, elem) => elem.size + len}    //> res1: Int = 16

Write a Censor trait with a method that will replace the curse words Shoot and Darn with Pucky and Beans alternatives. Use a map to store the curse words and their alternatives. Then, load the curse words and alternatives from a file:
The trait expects the curse words dictionary in the file words.txt:
Shoot:Pucky
Darn:Beans
The words are loaded line by line, each line is splitted at the : character and the values are stored in the substitions map. The replace method takes a text as input parameter, converts it as a list of words and applies the substitutions by looking up the map.
  trait Censor {
   val substitutions = new HashMap[String, String]
   
   Source.fromFile("/words.txt", "US-ASCII").getLines.foreach { line =>
    val elem = line.split(":", 2)
    substitutions += (elem(0) -> elem(1))
   }
   
   def replace(text: String): String = {
    text.split("\\s").map({word =>
     substitutions.getOrElse(word, word)
    }).reduceLeft((concat, word) => concat + " " + word)
   }
  }
Here's a simple example showing how the trait works:
  val censor = new Censor {}
  censor.replace("hello Darn world") //> res2: String = hello Beans world
Stay tuned, I'll soon be posting the 3rd study section about Scala.

Wednesday, September 26, 2012

vortex7

About a year ago I stumbled upon the Over The Wire hacker challenges and started solving the first set of levels (called vortex). Since then, I have been publishing my solutions in my blog. Here is vortex level 7:

The code

int main(int argc, char **argv)
{
        char buf[58];
        u_int32_t hi;
        if((hi = crc32(0, argv[1], strlen(argv[1]))) == 0xe1ca95ee) {
                strcpy(buf, argv[1]);
        } else {
                printf("0x%08x\n", hi);
        }
}

The vulnerability exposed in this code is a basic buffer overflow with two subtleties:

  1. The CRC of the buffer must equate to a given value (0xe1ca95ee)
  2. The buffer is rather small (58 bytes)

Manipulating the checksum

The cyclic redundancy check (CRC) computes a check value (or checksum), which is used to detect accidental changes in data, e.g. when transmitting over unreliable communication channels. With this error detecting code, the slightest change (i.e. bit-flip) in the input data results in a very different output pattern. As opposed to cryptographic hash functions like SHA1 or MD5, preimage resistance is not a property of CRC, it is not designed to withstand preimage attacks: given a checksum C, it is not hard to find an input m such that CRC(m) = C. As such, one shouldn't rely on it for integrity checks over insecure channels since it is very easy to manipulate it as is shown in the solution.

To solve this level, I chose to apply the CRC-reversing algorithm described in Reversing CRC – Theory and Practice, which by the way also contains a very nice introduction to CRC. The method consists in appending a 32-bit pattern to the buffer in order to adjust the CRC-remainder to the desired checksum. The same principle is proposed in the suggested lecture, CRC and how to Reverse it. But as opposed to the first approach which uses the inverse of the divisor polynomial, the bit pattern is derived using a system of equations.

Overflowing the buffer

This level contains a classic vulnerability which can easily be exploited to execute arbitrary code: a buffer overflow. The use of the strcpy standard library function to copy a buffer of data to another completely disregards the destination's capacity. If the source buffer is larger than the destination, all bytes will be copied, even though the destination's bound has been exceeded, and in doing so, subsequent structures in memory will be destroyed.

Intercepting the instruction pointer

Depending where the destination buffer is located in the process memory, it may be possible for an attacker to take influence on the program execution flow. In this case, the destination buffer is on the stack. By overflowing the buffer, copying bytes past its bound, the stored eip value will be overwritten. This is a pointer to the next instruction to return to after leaving the current stack frame, i.e. when returning from the current function call. With a meaningful value, it is possible to redirect the execution of the program to any executable location in memory.

Creating a shellcode

The payload we want to execute consists in a small fragment of x86 machine instructions, which perform 2-3 syscalls that allow us to run a shell:

  • geteuid()/setreuid() are used to set the effective user-id. The exploited binary runs with the suid-bit, which means the process is executed in the name of the file owner (the user that has read-privileges for the next level's password file).
  • execve() is called to run /bin/bash.

The original x86/asm code can be found here. Check out the Makefile to see how it is compiled and the raw instruction data is extracted. It is then necessary to encode the data to avoid specific patterns such as \0 bytes. I used metasploit's msfencode tool for this.

Executing arbitrary code

Since the buffer is rather small (58 bytes), it is difficult to dissimulate the malicious payload. An alternative way to include arbitrary data into the process memory is to define an evironment variable containing the data. It will be accessible from the beginning of the stack. The buffer must then overflow the saved eip value to point at the corresponding region in memory. Unfortunately, this address cannot be precisely deduced. Therefore, a common strategy consists in prepending a large number of nop instructions before the shellcode. This extends the landing platform of the target address thus increasing the probability of hitting the shellcode.

The exploit

The finalized exploit is available here. It is a C wrapper which prepares a shellcode and the buffer contents and calls the binary to exploit. I employed following methods from SAR-PR-2006-05 to implement the table driven CRC32 algorithm:

  • make_crc_table()
  • crc32_tabledriven()
  • fix_crc_end()

Since at first the resulting checksum values did not match the ones generated by vortex7 I additionally extracted the CRC32 table from the binary and stored them in crc_table_static. I realized that the vortex7 implementation actually uses 0x00000000 instead of 0xFFFFFFFF for INITXOR and FINALXOR.

The fix_crc_end() function adjusts the buffer such that its checksum eventually results in the desired value 0xe1ca95ee.

make_buffer() creates the data used to overflow the buffer. It contains a repetitive sequence of the target address. It allows to shift the sequence bytewise in order to adjust its alignment. make_payload() generates the buffer which contains the nop sled and the shellcode.

Finally, the wrapper executes vortex7, passing the address buffer as a command line argument and the payload in the environment variables.

The program expects two arguments:

  1. An offset for the target address, relative to the environment pointer taken from the current process (the wrapper).
  2. An alignment index (0-4) used to align the target address in the buffer.

Following arguments worked for me:

$ ./v7_wrapper 0 2
Using address: 0xFFFFD91F
$ whoami
vortex8

The password for the next level is then retrieved from the password file for the next level:

$ cat /etc/vortex_pass/vortex8 
X70A_gcgl

That's it! If you want to learn more about buffer overflows, I suggest you read Smashing the Stack for Fun and Profit by aleph1, originally posted in Phrack Magazine. Also have a look at my blog where I regularily publish vortex level solutions: blog.ant0i.net

Sunday, August 19, 2012

Seven Languages in Seven Weeks - Scala Day 1 Self Study

It's time for the next programming language in Seven Languages in Seven Weeks: Scala!
The self-study assignment consists in writing a program that will take a tic-tac-toe board and determine which player won (if any):
import scala.io.Source;

object TicTacToe extends App {

  val wins = List(
    List(0, 1, 2), List(3, 4, 5), List(6, 7, 8),
    List(0, 3, 6), List(1, 4, 7), List(2, 5, 8),
    List(0, 4, 8), List(2, 4, 6)
  )
  val input = Source.fromFile("tictactoe.txt").mkString
  val board = (for (chars <- "X|O".r findAllIn input) yield chars).toList

  if (isWin("X")) {
    if (isWin("O")) {
      println("Tie")
    } else {
      println("Player X wins")
    }
  } else {
 if (isWin("O")) {
      println("Player O wins")
 } else {
   println("No winner")
 }
  }

  def isWin (char: String): Boolean = {
    for (win <- wins) {
      var result = true
      for (x <- win) {
        result &= board(x) == char
      }
      if (result)
        return true
    }
 return false
  }
}

Monday, August 13, 2012

vortex6

The goal of vortex level 6 is to reverse engineer a binary executable to exploit it. I used objdump to decompile the code section. Check out the solution on github: https://github.com/antoinet/vortex/tree/master/vortex06

Sunday, July 29, 2012

Flattr on Dailymotion

Do you know Dailymotion? It's one of the leading video streaming platforms on the net. And ever head of flattr? It's a social micro-payment system, that allows making small donations to support people for the content they share on the web (e.g. check out the excellent metaebene.me blogs). I like to think of the flattr-button as facebook's like-button with a small contribution for every click. An interesting fact: flattr was initated amongst others by Peter Sunde, a co-founder of thepiratebay.org.

End of April 2012, Dailymotion integrated flattr into their platform, enabling video creators to insert a flattr button on their pages. Here's how the idea was born. My brother works for Dailymotion. He once skyped me up to tell me the company was going to hold a hackathon to promote innovative projects. He asked me if I had any suggestions. I called out to my colleague David who almost instantly mentioned flattr. I replied and some time later the idea was accepted by management. My brother's team didn't win the contest, but as he told me, it's the only project that turned productive.

This has some echo on the web: wired.com, techcrunch.com, venturebeat.com, they all covered the story. David and I were pretty astonished by the impact his idea had had. So if you'd like to give him some credit, go ahead and >>flattr him<<, I think he deserves it :-)

For your entertainment (if you speak french), here's the log transcript of our skype conversation:
23.11.11 15:31
un hackaton aura lieu de mardi a mercredi prochain ici
23.11.11 15:32
avec une tablette pour l'equipe gagnante
23.11.11 15:33
t'as pas des idees?
23.11.11 15:33
un truc qui revolutionne la facon dont tu regardes les videos et qui prends 10 ligne de code
23.11.11 15:33
lol
Antoine 23.11.11 15:35 
oh wow.
23.11.11 15:35
je veux le tablet
yann 23.11.11 15:35 
hihi
23.11.11 15:35
yeah moi aussi
Antoine 23.11.11 15:36 
des videos pr0n$
yann 23.11.11 15:36 
haha
23.11.11 15:36
oui
Antoine 23.11.11 15:36 
en 3d
yann 23.11.11 15:36 
yeah
23.11.11 15:36
ya deja un mec qui dev la 3d ici
Antoine 23.11.11 15:37 
cool
yann 23.11.11 15:37 
il a des lunettes lol
Antoine 23.11.11 17:05 
une idée d'un de mes collègues:
23.11.11 17:05
incorporer http://flattr.com/ pour le content dailymotion.
yann 23.11.11 17:06 
yeah this is nice bro
Antoine 23.11.11 17:07 
tu connais?
yann 23.11.11 17:07 
un petit peu
23.11.11 17:07
juste le principe
23.11.11 17:07
c'est de la remuneration sur le contenu
23.11.11 17:07
si ca te plait tu peux remunerer l'auteur
yann 23.11.11 17:11 
yeah
23.11.11 17:11
jvais lire flattr
23.11.11 17:12
faut voir mec
Antoine 23.11.11 17:13 
ouais. ce serait cool mec.
yann 23.11.11 17:13 
carrement
23.11.11 17:18
c'est une bonne idee
23.11.11 17:19
LET'S GET THIS TABLET!!

Wednesday, July 18, 2012

vortex5

Vortex level 5 consists in cracking a password hashed with MD5, which is called a preimage attack. No salt was used when applying the hash function, this makes it very easy by today's means to find the originating value.

The fastest way I found to achieve this is searching for the hash value with Google. Of course this will return lots of references to this level's solution, but you'll also get results for some websites that publish datasets of precomputed hashes, like for example md5crack or md5this.

Alternatively, you could crack the MD5 hash using some tool such as John The Ripper to perform a brute force attack. In the worst case this could result in computing all 62^5 combinations of the password (it was specified to be 5 characters long and consisting of a-zA-Z0-9). To restrict the number of tries, you can provide a wordlist of plausible passwords. Obviously, this will only generate a result if the password already existed in the list. This method works best when using real password data (e.g. from a leaked password database), since people tend to use similar patterns and also reuse their passwords.

Other tools such as RainbowCrack perform the attack using a rainbow table: a data structure used for the efficient storage of precomputed hash values. As for the websites mentioned above, you can easily get ahold of various tables, ranging from 50 to 500GB depending on the space of hashed values.

Saturday, July 14, 2012

Monday, June 18, 2012

Seven Languages in Seven Weeks - Prolog Day 3 Self Study

Time to catch up with Seven Languages in Seven Weeks! This is the last chapter on Prolog and here are the tasks:

  • Modify the Sudoku solver to work on six-by-six puzzles (square are 3x2) and 9x9 puzzles
  • Make the Sudoku solver print prettier solutions

Note: since I am using SWI Prolog instead of gprolog as used in the book, there are a few differences:

Here's the solution for six-by-six puzzles:
:- use_module(library(clpfd)).
valid([]).
valid([H|T]) :- all_different(H), valid(T).

sudoku(Puzzle, Solution) :-
 Solution = Puzzle,
 Puzzle = [
  S11, S12, S13, S14, S15, S16,
  S21, S22, S23, S24, S25, S26,
  S31, S32, S33, S34, S35, S36,
  S41, S42, S43, S44, S45, S46,
  S51, S52, S53, S54, S55, S56,
  S61, S62, S63, S64, S65, S66
 ],
 Puzzle ins 1..6,
 Row1 = [S11, S12, S13, S14, S15, S16],
 Row2 = [S21, S22, S23, S24, S25, S26],
 Row3 = [S31, S32, S33, S34, S35, S36],
 Row4 = [S41, S42, S43, S44, S45, S46],
 Row5 = [S51, S52, S53, S54, S55, S56],
 Row6 = [S61, S62, S63, S64, S65, S66],
 Col1 = [S11, S21, S31, S41, S51, S61],
 Col2 = [S12, S22, S32, S42, S52, S62],
 Col3 = [S13, S23, S33, S43, S53, S63],
 Col4 = [S14, S24, S34, S44, S54, S64],
 Col5 = [S15, S25, S35, S45, S55, S65],
 Col6 = [S16, S26, S36, S46, S56, S66],
 Rect1 = [S11, S12, S13, S21, S22, S23],
 Rect2 = [S14, S15, S16, S24, S25, S26],
 Rect3 = [S31, S32, S33, S41, S42, S43],
 Rect4 = [S34, S35, S36, S44, S45, S46],
 Rect5 = [S51, S52, S53, S61, S62, S63],
 Rect6 = [S54, S55, S56, S64, S65, S66],
 valid([Row1, Row2, Row3, Row4, Row5, Row6,
  Col1, Col2, Col3, Col4, Col5, Col6,
  Rect1, Rect2, Rect3, Rect4, Rect5, Rect6]).

pretty_print(Puzzle) :-
 writef("\
 +-----+ +-----+\n\
 |%d %d %d| |%d %d %d|\n\
 |%d %d %d| |%d %d %d|\n\
 +-----+ +-----+\n\n\
 +-----+ +-----+\n\
 |%d %d %d| |%d %d %d|\n\
 |%d %d %d| |%d %d %d|\n\
 +-----+ +-----+\n\n\
 +-----+ +-----+\n\
 |%d %d %d| |%d %d %d|\n\
 |%d %d %d| |%d %d %d|\n\
 +-----+ +-----+", Puzzle).

Saturday, June 16, 2012

How to enable IP Forwarding in Mac OS X

Another note to self: how to enable IP forwarding in Mac OS X:
sudo sysctl -w net.inet.ip.forwarding=1
(credit: Stack Exchange)

Sunday, June 10, 2012

vortex3 (reloaded)

In the original vortex3 post, I wasn't able to reproduce the exploit since the vortex levels were recompiled with a newer version of gcc. Thanks to some hints from the vortex admins, I managed to solve the level using another approach. Here are my notes from github:

Obviously, the objective of this level is to overflow buf which will allow to overwrite lpp. In turn, buf's address will be written to wherever *lpp points to. By selecting an appropriate memory location for lpp, it will be possible to inject &buf as a function pointer into some data structure that will later execute it. I tried two approaches:
  • Overwriting an entry of the .dtors section, which contains a list of destructors, each called subsequently before program termination.
  • Overwriting an entry of the .plt/.got sections, the dynamic linking structure which resolves the position of shared library functions such as exit().

I guess the original intent to solve this level was to use the first approach, induced by the suggested reading material. In the mean time, the vortex wargames have been recompiled with a newer version of gcc and unfortunetaly, the .ctors/.dtors sections are no longer writable, as mentioned by the vortex admins. In a second notice, they suggest to brute force the 2^16 possible values and draw own conclusions. This resulted in 3 address values which led to a successful exploit: 0x0804928c, 0x080492cc and 0x08049306. Interestingly enough, these memory locations originate from a read/write memory location, where the program text is loaded. But the program text is actually executed from the 4k memory region starting at 0x08048000. Comparing the dumps of both regions 0x08048000-0x08049000 (read/execute) and 0x08049000-0x0804a000 (read/write), I realized that they almost match, the only differences several are unitialized memory addresses in the latter. From there on, I started reading about the loading process and dynamic linking in order to understand the meaning of this memory layout. I concluded that the raw program text is loaded in the higher memory region. During initialization, the loader copies its contents and completes missing references to several dynamic process structures such as the .got and the .plt starting at 0x08048000.

Following the pointers from 0x0804928c, we see that it leads to the .plt at 0x0804962c (exit@got.plt) and eventually to the exit() function from the dynamically linked libc at 0x0804830a (). Following the double indirection (**lpp), the .plt entry for exit() is therefore overwritten and program execution will jump to &buf instead of exit() when called at the end of the main function.

Saturday, June 9, 2012

Neue Zürcher Zeitung Binary Issue


Last Friday, I was surprised to notice that the front page of the Neue Zürcher Zeitung's daily edition was scattered with nothing but zeros and ones. At first, I thought this had to be some kind of a printing defect, similar to the illegible raw output of a PDF. But then I realized that the gothic letters in the title were also affected by the anomaly; this couldn't be a mistake.

Sure enough, this was just a bogus cover page in front of the real title page to advertise the newspaper's new online archive. After manually decoding the first value 01001110 (N) together with the following 01011010 (Z) occuring twice, I knew the rest of the page couldn't be random, so I decided to unveil the hidden text...

First step was to get a digitized version of that newspaper issue. Scanning it wasn't necessary since it's available online. I then used tesseract, an OCR engine to retrieve the strings from the image file (note: this isn't even necessary since one can just copy-paste the contents from the PDF, but it's just more fun). Finally, I hacked the following ruby script to convert the binary data into characters:
#!/usr/bin/ruby

puts "converting file #{ARGV[0]}"
str = IO.read(ARGV[0]).gsub(/[^01]/, '')
puts str
for i in 0..str.length/8
 print str[i*8, 8].to_i(2).chr
end
puts
The result: the encoded texts correspond to the articles of the real front page. Of course, they had to be shortened to fit. I was a bit disappointed though not to find any easter eggs :( Still, it was a good distraction :)

Thursday, June 7, 2012

LinkedIn Password Data Leaked

As reported by several security related online portals, a file with approx. 6.5 mio SHA-1 password hashes from LinkedIn users is currently circulating the web. I could easily get ahold of a copy of that 250 Mb file through bittorrent and realized that my password matched an entry :(.

Here's how you can check:
$ echo -n "password" | shasum
$ grep 5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8 SHA1.txt
$ grep 000001e4c9b93f3f0682250b6cf8331b7ee68fd8 SHA1.txt 
000001e4c9b93f3f0682250b6cf8331b7ee68fd8

As mentioned here, a subset of the hashes are marked with 00000, presumably to identify already cracked passwords. You should therefore check both variants as shown above.

If your password matches, you should change your LinkedIn Password asap and then change your passwords everywhere where you reused it (especially for popular platforms like Facebook, Google or Amazon).

Thursday, May 24, 2012

How to disable ASLR in Linux

Quick note to self on how to disable ASLR (address space layout randomization) in Ubuntu Linux:
$ sudo sh -c "echo 0 > /proc/sys/kernel/randomize_va_space"

Did you just email me back my own password?!

A while ago I wrote a blog post about what precautions to take handling password data on your website. plaintextoffenders.com is a website dedicated to this issue. It nicely points out why storing passwords in plaintext really is such a bad idea. The main part of the website is a pillory of submitted websites which obviously apply bad password practices. There's for awareness...

Thursday, April 26, 2012

Seven Languages in Seven Weeks - Prolog Day 2 Self-Study

More fun with prolog! This self-study section consists in implementing some list operations.

Reverse the elements of a list
rev([], []).
rev([Head|Tail], List) :- append(X, [Head], List), rev(Tail, X).

Find the smallest element of a list.
min([X], X).
min([Head1|[Head2|Tail]], X) :- Head1 =< Head2, min([Head1|Tail], X).
min([Head1|[Head2|Tail]], X) :- Head1 > Head2, min([Head2|Tail], X).

Sort the elements of a list.
insert(X, [], [X]).
insert(X, [H|T], [X,H|T]) :- X =< H.
insert(X, [H|T], [H|Rest]) :- X > H, insert(X, T, Rest).

isort([], Acc, Acc).
isort([H|T], Acc, Sorted) :- insert(H, Acc, Acc2), isort(T, Acc2, Sorted).

Wednesday, April 25, 2012

Seven Languages in Seven Weeks - Prolog Day 1 Self-Study

For this book's section about prolog, I'll be using SWI-Prolog, as I'm currently getting an error installing the gnu-prolog macport. Here's the link to the SWI-Prolog online reference.

Make a simple knowledge base. Represent some of your favorite books and authors.
% books.pl
book(sevenLanguagesInSevenWeeks).
book(cleanCode).
book(cleanCoder).
book(programmingInScala).
author(odersky).
author(tate).
author(martin).
wrote(odersky, programmingInScala).
wrote(tate, sevenLanguagesInSevenWeeks).
wrote(martin, cleanCode).
wrote(martin, cleanCoder).

Find all books in your knowledge base written by one author.
?- ['books'].
% books compiled 0.00 sec, 13 clauses
true.

?- wrote(martin, X).
X = cleanCode ;
X = cleanCoder.

Make a knowledge base representing musicians and instruments. Also represent musicians and their genre of music.
% music.pl
instrument(flea, bass).
instrument(hendrix, guitar).
instrument(hancock, piano).
instrument(cash, guitar).
genre(flea, funk).
genre(hendrix, blues).
genre(hancock, jazz).
genre(cash, country).

Find all musicians who play the guitar.
?- ['music'].
% music compiled 0.00 sec, 10 clauses
true.

?- instrument(X, guitar).
X = hendrix ;
X = cash.

Wednesday, April 4, 2012

How to get a List of Installed JVMs on a Mac

I got this tip from a fellow worker:
$ /usr/libexec/java_home -V
This command will get you the list of installed Java Virtual Machines installed on your Mac OS X system.

Sunday, April 1, 2012

Inspecting the Process Environment Variables with GDB

While trying to solve the 4th level of the vortex wargame, I found it was necessary to learn how to inspect the location and content of the environment variables within the process memory.

GDB has built-in commands to inspect the process environment, see the GDB manual. You can either list all environment variables or a specific one (e.g. FOOBAR) using the following commands, which will output their values:
(gdb) show environment
(gdb) show environment FOOBAR
In order to locate the environment variables within the process memory, you can query the variable char** environ (see the libc reference and this entry on stack overflow):
(gdb) x/s *((char **)environ)
This will print the location of the first environment variable and its representation as string. To print the next variables, simply add an offset to the variable:
(gdb) x/s *((char **)environ + 1)

I also found these links to be useful:

Wednesday, March 28, 2012

Seven Languages in Seven Weeks - Io Day 3 Self-Study

It's been some time now, still I'm keeping up reading Seven Languages in Seven Weeks. Here's the last self-study section about the Io programming language.

Enhance the XML program to add spaces to show the indentation structure.

Builder := Object clone
Builder numIndents := 0
Builder doIndents := method (for (i, 1, numIndents, write(" ")))
Builder openTag := method(name, doIndents; writeln("<", name, ">"))
Builder closeTag := method(name, doIndents; writeln("</", name, ">"))
Builder forward := method (
  openTag(call message name);
  numIndents = numIndents + 1;
  call message arguments foreach (
    arg,
    content := self doMessage(arg);
    if (content type == "Sequence", doIndents; writeln(content))
  );
  numIndents = numIndents - 1;
  closeTag(call message name)
)

Builder ul(
  li("Javascript"),
  li("Lua"),
  li("Javascript")
)

Create a list syntax that uses brackets

squareBrackets := method(call message arguments)

Enhance the XML program to handle attributes: if the first argument is a map (use the curly brackets syntax), add attributes to the XML program. For example: book({"author": "Tate"}...) would print <book author="Tate">.

OperatorTable addAssignOperator(":", "atPutNumber")
Map atPutNumber := method(
  self atPut(
    call evalArgAt(0) asMutable removePrefix("\"") removeSuffix("\""),
    call evalArgAt(1)
  )
)
curlyBrackets := method(
  map := Map clone;
  call message arguments foreach(arg, map doMessage(arg));
  map
)

Builder := Object clone
Builder numIndents := 0
Builder doIndents := method (for (i, 1, numIndents, write(" ")))
Builder doAttributes := method(map, map keys foreach(key, write(" ", key, "=\"", map at(key) ,"\"")))
Builder forward := method (
  doIndents; write("<", call message name);
  if(call message arguments size == 0, writeln(">"));
  numIndents = numIndents + 1;
  call message arguments foreach (i, arg,
    content := self doMessage(arg);
    if (i == 0, 
      if(content type == "Map", doAttributes(content));
      writeln(">")
    )
    if (content type == "Sequence", doIndents; writeln(content));
  );
  numIndents = numIndents - 1;
  doIndents; writeln("</", call message name, ">")
)

Monday, March 12, 2012

Seven Languages in Seven Weeks - Io Day 2 Self-Study

Here's the next self-study section about the Io programming language. These are several exercises to get some practice.

A Fibonacci sequence starts with two 1s. Each subsequent number is the sum of the two numbers that came before; 1, 1, 2, 3, 5, 8, 13, 21, and so on. Write a program to get the nth Fibonacci number. fib(1) is 1, and fib(4) is 3. As a bonus, solve the problem with recursion and with loops

The recursive approach (very concise):
fib := method(n,  if (n <= 2, 1, fib(n-1) + fib(n-2)))
And with a loop:
fib := method(n,
  p := 1;
  q := 1;
  sum := 1;
  for (i, 3, n,
    sum := p + q;
    p := q;
    q := sum
  );
  sum
)
How would you change / to return 0 if the denominator is zero?
Number div := Number getSlot("/")
Number / := method(n, if (n == 0, 0, self div(n))
Write a program to add up all of the numbers in a two-dimensional array.
a := list(list(1, 2, 3, 4), list(5, 6, 7, 8))
s := 0
a foreach(sublist, s := s + sublist sum)
Or more concise:
a flatten sum
Add a slot called myAverage to a list that computes the average of all the numbers in a list. What happens if there are no numbers in a list? (Bonus: Raise an Io exception if any item in the list is not a number.)
List myAverage := method(self sum / self size)
And with exception handling:
List myAverage := method(
  sum := 0;
  self foreach(e,
    (e isKindOf(Number)) ifFalse(Exception raise("not a number"));
    sum := sum + e
  );
   sum / self size
)
Write a prototype for a two-dimensional list. The dim(x, y) method should allocate a list of y lists that are x elements long. set(x, y, value) should set the value, and get(x, y) should return that value
List2d := Object clone

List2d dim := method(x, y,
  self rows := List clone;
  for (i, 1, x,
    cols := List clone;
    for (j, 1, y,
      cols append(nil)
    );
    self rows append(cols)
  );
  self
)

List2d set := method(x, y, value, 
  self rows at(x) atPut(y, value);
  self
)

List2d get := method(x, y, 
  self rows at(x) at(y)
)
Bonus: write a transpose method so that (new_matrix get(y, x)) == matrix get(x, y) on the original list.
List2d transpose := method(
  transposed := List2d clone;
  transposed dim(self rows at(0) size, self rows size);
  self rows foreach(i, row, 
    row foreach(j, elem,
      transposed set(j, i, elem)
    );
  );
  transposed;
)
Write the matrix to a file, and read a matrix from a file
List2d toFile := method(filename,
  file := File clone open(filename);
  self rows foreach(col, 
    col foreach (elem,
      file write(elem asString, " ")
    );
    file write("\n")
  );
  file flush close;
  file
)

List2d fromFile := method(filename,
  self rows := List clone;
  file := File clone open(filename);
  file readLines foreach(line,
    cols := line split;
    self rows append(cols)
  );
  self
)
Write a program that gives you ten tries to guess a random number from 1--100. If you would like, give a hint of "hotter" or "colder" after the first guess.
secretNum := Random value(100) floor() + 1
in := File standardInput
for (i, 1, 10,
  write("Guess number (try #", i, "): ");
  guess := in readLine asNumber;
  if (guess == secretNum, write("Win!"); break);
  if (i > 1, 
    if ((secretNum - guess) abs < (secretNum - previousGuess) abs,
      write("hotter\n"),
      write("cooler\n")
    )
  );
  previousGuess := guess;
)

Thursday, March 8, 2012

Seven Languages in Seven Weeks - Io Day 1 Self-Study

Here's the first self-study section about the Io programming language. I didn't know Io before, I still find it a bit awkward, but I'm beginning to like it.

Evaluate 1 + 1 and then 1 + "one". Is Io strongly typed or weakly typed? Support you answer with code.
Io> 1 + 1
==> 2
Io> 1 + "one"

  Exception: argument 0 to method '+' must be a Number, not a 'Sequence'
  ---------
  message '+' in 'Command Line' on line 1
Io is strongly typed, operands of different types will not be implicitly converted:
Io> 1 + "2"

  Exception: argument 0 to method '+' must be a Number, not a 'Sequence'
  ---------
  message '+' in 'Command Line' on line 1
Is 0 true or false? What about the empty string? Is nil true or false? Support your answer with code.
Io> 0 and true
==> true
Io> "" and true
==> true
Io> nil and true
==> false
How can you tell what slots a prototype supports?

Invoking an object in the prompt will print the supported slots:
Io> Car
==>  Car_0x7fb039c9a1f0:
  type             = "Car"
  vroom            = method(...)
The slotNames message returns the list of slots:
Io> Car slotNames
==> list(type, vroom)
To get the slots defined by the parent, call the proto message:
Io> Car proto
==>  Vehicle_0x7fb039c6e270:
  description      = "Something that takes you far away"
  type             = "Vehicle"
What is the difference between = (equals), := (colon equals), and ::= (colon colon equals)? When would you use each one?
=Assigns value to slot if it exists, otherwise raises exception
:=Creates slot, assigns value
::=Creates slot, creates setter, assigns value
Run an Io program from a file
$ echo '"Hello, world!" println' > helloworld.io
$ io helloworld.io 
Hello, world!
Execute the code in a slot given its name

Unfortunately, I haven't been able to solve this one yet. I guess the intent is given a slot holding some code as a string, one should figure out a statement to execute this code.
Io> code := "\"hello\" println"
==> "hello" println

Sunday, March 4, 2012

Password Security 101 for Web Developers

Passwords are still the only mean of authentication for I'd say 99.95% of all online services including social networking sites, online shops and even e-banking applications. When you think about the consequences of a password theft, say for your personal email account, you'll soon realize that a password such as 123456, iloveyou or your mom's birthdate is totally insufficient... (see this and change your password everywhere if you get a match).

There a lots of articles that will tell you what a (more) secure password looks like (I especially like this one as well as it's illustration). And although many web sites will impose some password policy during registration that will reject any password unless it contains some digit or special characters, the choice (and the complexity) is ultimately left to the user. What's unavoidable is that users are almost certainly going to reuse at least one password sometime for one or the other online service. Haven't you also? (don't blush).

So what can you as a developer do about it? I don't know, but I can tell you what you should totally avoid if you don't want yourself and your company to be looked at as total newbs.

First realize that passwords are the user's good and you are due to treat that information with absolute care. Every single one of your clients has spent the effort of selecting some unnatural string, repeating the process until it complied with your password policy and spending the rest of the day trying not to forget it. This is the reason why user's will eventually reuse a password. So bear in mind, that you're not storing a user's password for your web application only, but most probably also for a number of other services the user has registered to. Respecting your client's integrity means that you will never disclose that data, not even internally within your company.

The most important precaution you should take when dealing with password data is: never ever store passwords in clear text. No system is safe enough, not even yours. And the risk's not worth it. If you don't know how to avoid storing passwords in clear text, learn about hash functions and salting.

Second rule: never ever send a password back to the user (for instance via email). This is totally unprofessional. You're not only showing your client that you're storing passwords in clear text (i.e. that you're a newb), you're also compromising his password by sending it over an unsecure channel.

I assume companies do this to reduce support cases related to lost passwords. They should rethink it all over. Recent attacks have shown how much damage is caused to the company (reputation) as well as to their clients by having confidential user data stolen. Think about RSA, the Sony Playstation network or recently Youporn (should you not know, the most popular pornographic website)...

Friday, March 2, 2012

Seven Languages in Seven Weeks - Ruby Day 3 Self Study

Hi again. Here's the self-study section for day 3 from the book Seven Languages in Seven Weeks, the last one about ruby.

Modify the CSV application to support an each method to return a CsvRow object. Use method_missing on that CsvRow to return the value for a given heading.
module ActsAsCsv
  
  def self.included (base)
    base.extend ClassMethods
  end
  
  module ClassMethods
    
    def acts_as_csv
      include InstanceMethods
    end
    
    module InstanceMethods
      
      class CsvRow
        def initialize (headers, row)
          @headers = headers
          @row = row
        end
        
        def method_missing (name, *args)
          index = @headers.index(name.to_s)
          @row[index] unless index.nil?
        end
      end
      
      def read
        @csv_contents = []
        filename = self.class.to_s.downcase + '.txt'
        file = File.new(filename)
        @headers = file.gets.chomp.split(', ')
        file.each do |row|
          @csv_contents << CsvRow.new(headers, row.chomp.split(', '))
        end
      end
      
      attr_accessor :headers, :csv_contents
      
      def initialize
        read
      end
      
      def each (&block)
        @csv_contents.each(&block)
      end
    end
  end
end

Wednesday, February 29, 2012

Seven Languages in Seven Weeks - Ruby Day 2 Self-Study

These are my answers to the 2nd self-study section of Seven Languages in Seven Weeks, enjoy.

Find out how to access files with and without code blocks. What is the benefit of the code block?
file = File.open("hello.txt")
line = file.readline
until line.nil? 
  puts line
  line = file.readline
end
file = File.open("hello.txt")
file.each { |line| puts line }
Latter variant is far more concise. Also, using a code block one avoids dealing with the file object's state.

How would you translate a hash to an array? Can you translate arrays to hashes?
Taking a hash, one can convert it into an array of key-value pairs:
hash.each_pair { |key, value| array.push([key, value]) }
Taking an array, one can map each value to its index (which becomes the key):
array.each_with_index { |item, index| hash[index] = item }

Can you iterate through hash?
Yes, using each_pair (see also example above).

You can use Ruby arrays as stacks. What other common data structures do arrays support?
Ruby arrays provide the push and pop stack operations. To use an array as a queue, use push to enqueue and shift to dequeue items. List operations are supported using methods like first, insert, etc.

Print the contents of an array of sixteen numbers, four numbers at the time, using just each.
i = 1
array.each do |x|
  print x, ' '
  puts if i % 4 == 0
  i += 1
end

Now, do the same with each_slice in Enumerable.
array.each_slice(4) { |slice| p slice }

The Tree class was interesting, but it did not allow you to specify a new tree with a clean user interface. Let the initializer accept a nested structure of hashes. You should be able to specify a tree like this: {'grandpa' => {'dad' => {'child 1' => {}, 'child 2' => {} }, 'uncle' => {'child 3' => {}, 'child 4' => {} } } }.
class Tree
  attr_accessor :children, :node_name
  
  def initialize (name, children={}) 
    @node_name = name
    @children = []
    children.each_pair {|key, val| @children << Tree.new(key, val) }
  end
  
  def visit_all (&block)
    visit &block
    children.each {|c| c.visit_all &block}
  end
  
  def visit (&block)
    block.call self
  end
end
Write a simple grep that will print the lines of a file having any occurrences of a phrase anywhere in that line. You will need to do a simple regular expression match and read lines from a file. (This is surprisingly simple simple in Ruby.) If you want, include line numbers.
def grep (pattern, filename)
  f = File.open(filename)
  f.each {|line| puts "#{f.lineno}: #{line}" if line =~ /#{pattern}/}
end

Monday, February 27, 2012

Seven Languages in Seven Weeks - Ruby Day 1 Self-Study

I started reading Seven Languages in Seven Weeks. I'll be posting some of my answers to the self-study section at the end of each chapter, mainly for self-documentation.

Some links:

Print the string "Hello, world."
>> puts "Hello, World"
Hello, World
=> nil

For the string "Hello, Ruby", find the index of the word "Ruby"
>> "Hello, Ruby".index("Ruby")
=> 7

Print your name ten times
>> 10.times { puts "ant0inet" }
ant0inet
ant0inet
ant0inet
ant0inet
ant0inet
ant0inet
ant0inet
ant0inet
ant0inet
ant0inet
=> 10

Run a Ruby program from a file.
$ cat > hello_world.rb << EOF
> #!/usr/bin/env ruby
> puts "Hello, world."
> EOF
$ ruby hello_world.rb 
Hello, world.

Write a program that picks a random number. Let a player guess the number, telling the player whether the guess is too low or too high.
#!/usr/bin/env ruby

random_num = rand(10) + 1
puts "Enter your guess:"
guess = gets.to_i
until guess == random_num
  if guess < random_num
    puts "too low"
  else
    puts "too high"
  end
  guess = gets.to_i
end 
puts "correct"