Preview.app PDF file size

You get a 11 Mb PDF from a (non-configurable) scanner and need to email/upload it to someone. You open it in Preview.app on osx, export, select the Reduce File Size quartz filter. Open the exported PDF.. and it looks like complete crap, not even remotely readable – thanks you so much Apple for the overzealous reduction filter.

Here is a custom one you can add to /System/Library/Filters and get actually readable and decently small PDFs, save it as Shrink.qfilter or similar.

[gist https://gist.github.com/stianeikeland/7897517]
Advertisements

$10 GPS

pciegpsOn ebay you can find cheap u-blox mini-pcie gps units for around $10 including shipping. They are for internal use in laptops and similar (most likely hooking up to the usb bus over Mini PCIe), but it turns out that the pads on the backside expose connectivity options such as uart and usb data.

I soldered on a pin header for ease of use, and also attached a cheap ceramic antenna using double sided tape.

The UART pins will spew over standard NMEA 183 data, so it should be easy to use with both computers and microcontrollers.

On the raspberry pi you can install the gpsd and gpsd-clients packages. Connect the tx gps pin to GPIO 15 RXD on the pi (you only really need one way uart, unless you want to change settings on the gps). Also connect ground and vcc, the gps requires 3.3v and probably need more umphf than the 50mA max 3.3 pin on the pi can deliver. I connected power via a 5v pin and a 3.3v regulator. I do not know if the gps is 5v tolerant, but probably not.

Launch the daemon ( gpsd -b /dev/ttyAMA0 ) and a client ( cgps ).. Remember to disable the tty running on /dev/ttyAMA0 before you use the UART pins for something like this.

Go GPIO library for Raspberry Pi

GopherBeen playing a bit with Go (-lang) lately, it seems like a fun little language. Very minimalistic and clean, yet quite powerful – you can do so many things with the simple constructs they provide (especially the goroutines, channels and type-system). Sadly, it looks like it’s pretty slow in benchmarks compared to the other natural alternatives – but it’s still early.

animatedAnyway, in an attempt to mix Gophers and Pi, I’ve made a small native GPIO library for Go on the Raspberry Pi (or the bcm2835 chipset in general). Nothing advanced, but it provides the usual suspects: PinMode (Output, Input), Write, Read, PullUp, PullDown, PullOff, etc. It works by memory-mapping the GPIO addresses in /dev/mem, so it will require root.

To use, and blink a little LED (“hello world” of the electronics/microcontroller realm) just do something like:


import (
	"fmt"
	"github.com/stianeikeland/go-rpio"
	"os"
	"time"
)

func main() {
	if err := rpio.Open(); err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
	defer rpio.Close()

	pin = rpio.Pin(10)
	pin.Output()

	for x := 0; x < 20; x++ {
		pin.Toggle()
		time.Sleep(time.Second)
	}
}

Available over at GitHub.

Would be awesome to add PWM, I2C, SPI, etc.. who knows, maybe one day..

OpenWRT on Hama MPR-A1 (v2.2)

201204160226342556Hama MPR-A1 is a tiny pocket router (ralink 5350f based, 360 mhz, 4 mb flash, 16 mb ram) that features a 1800 mah built in battery. I bought one on ebay for about $20 and wanted to get OpenWRT running on it. You can find patches for openwrt on 5350 here: OpenWrt-RT5350

You need a uart connection to flash this thing, so open it up and remove the battery from the backside of the PCB.

Apparently there are multiple revisions of MPR-A1 around, and mine was a bit different from the others I’ve been able to find on the internet. Mine had a layer of copper foil covering the PCB, I pealed it away to locate the RX/TX uart connections. Sadly, on my revision (2.2), the pads are covered with solder mask – I do not know if they are made this way now, or if mine was from a weird batch.

Anyway, I sanded down the solder mask to reveal the copper pads, and soldered RX, TX and GND to a UART usb adapter (from an old nokia connector in my case).

Be careful not to sand too much, the copper is pretty thin.

Next, prepare a suitable openwrt image, and set up a tftp server. On a mac it’s pretty easy and already built in, simply put the firmware in /private/tftpboot – to start the tftp daemon run:

sudo launchctl load -F /System/Library/LaunchDaemons/tftp.plist
sudo launchctl start com.apple.tftpd
# When done, substitute with unload and stop

Next, make a serial connection, screen is pretty nice for this on a mac: screen /dev/tty.usbserial 57600 ..
Power up the router and hold down ‘2’ .. (uboot will give you some boot options, 2 = flash from tftp). Connect via ethernet to the router and follow the tftp instructions.

============================================
Ralink UBoot Version: 3.6.0.0
--------------------------------------------
ASIC 5350_MP (Port5<->None)
DRAM_CONF_FROM: Boot-Strapping
DRAM_TYPE: SDRAM
DRAM_SIZE: 128 Mbits
DRAM_WIDTH: 16 bits
DRAM_TOTAL_WIDTH: 16 bits
TOTAL_MEMORY_SIZE: 16 MBytes
Flash component: SPI Flash
Date:Dec 13 2011  Time:13:49:42
============================================
icache: sets:256, ways:4, linesz:32 ,total:32768
dcache: sets:128, ways:4, linesz:32 ,total:16384

 ##### The CPU freq = 360 MHZ ####
 estimate memory size =16 Mbytes
raspi_read: from:40028 len:6
.
raspi_read: from:0 len:30004
....*************Is_update = 0 plat = 1**************

Please choose the operation:
   1: Load system code to SDRAM via TFTP.
   2: Load system code then write to Flash via TFTP.
   3: Boot system code via Flash (default).
   4: Entr boot command line interface.
   7: Load Boot Loader code then write to Flash via Serial.
   9: Load Boot Loader code then write to Flash via TFTP.

You choosed 2
                                                                                                                                                                                                                                          0

2: System Load Linux Kernel then write to Flash via TFTP.
 Warning!! Erase Linux in Flash then burn new one. Are you sure?(Y/N)
 Please Input new ones /or Ctrl-C to discard
        Input device IP (192.168.1.109) ==:10.0.0.2
        Input server IP (192.168.1.55) ==:10.0.0.1
        Input Linux Kernel filename () ==:mpr-a1-16m-luci-usb-mjpg.bin

 netboot_common, argc= 3

 NetTxPacket = 0x80FE6AC0

 KSEG1ADDR(NetTxPacket) = 0xA0FE6AC0

 NetLoop,call eth_halt !

 NetLoop,call eth_init !
Trying Eth0 (10/100-M)

 Waitting for RX_DMA_BUSY status Start... done

 Header Payload scatter function is Disable !!

 ETH_STATE_ACTIVE!!
Using Eth0 (10/100-M) device
TFTP from server 10.0.0.1; our IP address is 10.0.0.2
Filename 'mpr-a1-16m-luci-usb-mjpg.bin'.

 TIMEOUT_COUNT=10,Load address: 0x80100000
Loading: Got ARP REPLY, set server/gtwy eth addr (40:6c:8f:39:df:18)
Got it
#################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         ##########################################
done
Bytes transferred = 3538948 (360004 hex)
NetBootFileXferSize= 00360004
raspi_erase_write: offs:50000, count:360004
raspi_erase: offs:50000 len:360000
......................................................
raspi_write: to:50000 len:360000
......................................................
raspi_read: from:50000 len:10000
.raspi_read: from:60000 len:10000
.raspi_read: from:70000 len:10000
.raspi_read: from:80000 len:10000
.raspi_read: from:90000 len:10000
.raspi_read: from:a0000 len:10000
.raspi_read: from:b0000 len:10000
.raspi_read: from:c0000 len:10000
.raspi_read: from:d0000 len:10000
.raspi_read: from:e0000 len:10000
.raspi_read: from:f0000 len:10000
.raspi_read: from:100000 len:10000
.raspi_read: from:110000 len:10000
.raspi_read: from:120000 len:10000
.raspi_read: from:130000 len:10000
.raspi_read: from:140000 len:10000
.raspi_read: from:150000 len:10000
.raspi_read: from:160000 len:10000
.raspi_read: from:170000 len:10000
.raspi_read: from:180000 len:10000
.raspi_read: from:190000 len:10000
.raspi_read: from:1a0000 len:10000
.raspi_read: from:1b0000 len:10000
.raspi_read: from:1c0000 len:10000
.raspi_read: from:1d0000 len:10000
.raspi_read: from:1e0000 len:10000
.raspi_read: from:1f0000 len:10000
.raspi_read: from:200000 len:10000
.raspi_read: from:210000 len:10000
.raspi_read: from:220000 len:10000
.raspi_read: from:230000 len:10000
.raspi_read: from:240000 len:10000
.raspi_read: from:250000 len:10000
.raspi_read: from:260000 len:10000
.raspi_read: from:270000 len:10000
.raspi_read: from:280000 len:10000
.raspi_read: from:290000 len:10000
.raspi_read: from:2a0000 len:10000
.raspi_read: from:2b0000 len:10000
.raspi_read: from:2c0000 len:10000
.raspi_read: from:2d0000 len:10000
.raspi_read: from:2e0000 len:10000
.raspi_read: from:2f0000 len:10000
.raspi_read: from:300000 len:10000
.raspi_read: from:310000 len:10000
.raspi_read: from:320000 len:10000
.raspi_read: from:330000 len:10000
.raspi_read: from:340000 len:10000
.raspi_read: from:350000 len:10000
.raspi_read: from:360000 len:10000
.raspi_read: from:370000 len:10000
.raspi_read: from:380000 len:10000
.raspi_read: from:390000 len:10000
.raspi_read: from:3a0000 len:10000
.raspi_read: from:3b0000 len:10000
.raspi_erase: offs:3b0000 len:10000
.
raspi_write: to:3b0000 len:10000
.
raspi_read: from:3b0000 len:10000
.Done!
## Booting image at bc050000 ...
raspi_read: from:50000 len:40
.   Image Name:   MIPS OpenWrt Linux-3.7.5
   Created:      2013-04-11  15:04:48 UTC
   Image Type:   MIPS Linux Kernel Image (lzma compressed)
   Data Size:    915870 Bytes = 894.4 kB
   Load Address: 80000000
   Entry Point:  80000000
raspi_read: from:50040 len:df99e
..............   Verifying Checksum ... OK
   Uncompressing Kernel Image ... OK
No initrd
## Transferring control to Linux (at address 80000000) ...
## Giving linux memsize in MB, 16

Starting kernel ...

[    0.000000] Linux version 3.7.5 (lich@lich-pc) (gcc version 4.6.4 20121210 (prerelease) (Linaro GCC 4.6-2012.12) ) #1 Thu Apr 11 23:04:28 CST 2013
[    0.000000] bootconsole [early0] enabled
[    0.000000] CPU revision is: 0001964c (MIPS 24KEc)
[    0.000000] Ralink RT5350 id:1 rev:3 running at 360.00 MHz
[    0.000000] Determined physical RAM map:
[    0.000000]  memory: 01000000 @ 00000000 (usable)
[    0.000000] User-defined physical RAM map:
[    0.000000]  memory: 01000000 @ 00000000 (usable)
[    0.000000] Initrd not found or empty - disabling initrd
[    0.000000] Zone ranges:
[    0.000000]   Normal   [mem 0x00000000-0x00ffffff]
[    0.000000] Movable zone start for each node
[    0.000000] Early memory node ranges
[    0.000000]   node   0: [mem 0x00000000-0x00ffffff]
[    0.000000] Primary instruction cache 32kB, VIPT, 4-way, linesize 32 bytes.
[    0.000000] Primary data cache 16kB, 4-way, VIPT, no aliases, linesize 32 bytes
[    0.000000] Built 1 zonelists in Zone order, mobility grouping off.  Total pages: 4064
[    0.000000] Kernel command line:  board=MPR-A1 console=ttyS1,57600 mtdparts=spi0.0:192k(u-boot)ro,64k(u-boot-env)ro,64k(factory)ro,896k(kernel),2880k(rootfs),3776k@0x50000(firmware) rootfstype=squashfs,jffs2 mem=16M
[    0.000000] PID hash table entries: 64 (order: -4, 256 bytes)
[    0.000000] Dentry cache hash table entries: 2048 (order: 1, 8192 bytes)
[    0.000000] Inode-cache hash table entries: 1024 (order: 0, 4096 bytes)
[    0.000000] __ex_table already sorted, skipping sort
[    0.000000] Writing ErrCtl register=00000000
[    0.000000] Readback ErrCtl register=00000000
[    0.000000] Memory: 13388k/16384k available (1969k kernel code, 2996k reserved, 473k data, 180k init, 0k highmem)
[    0.000000] SLUB: Genslabs=9, HWalign=32, Order=0-3, MinObjects=0, CPUs=1, Nodes=1
[    0.000000] NR_IRQS:48
[    0.000000] console [ttyS1] enabled, bootconsole disabled
[    0.000000] console [ttyS1] enabled, bootconsole disabled
[    0.010000] Calibrating delay loop... 239.61 BogoMIPS (lpj=1198080)
[    0.080000] pid_max: default: 32768 minimum: 301
[    0.080000] Mount-cache hash table entries: 512
[    0.090000] NET: Registered protocol family 16
[    0.100000] MIPS: machine is HAME MPR-A1
[    0.130000] bio: create slab <bio-0> at 0
[    0.140000] Switching to clocksource MIPS
[    0.150000] NET: Registered protocol family 2
[    0.160000] TCP established hash table entries: 512 (order: 0, 4096 bytes)
[    0.180000] TCP bind hash table entries: 512 (order: -1, 2048 bytes)
[    0.190000] TCP: Hash tables configured (established 512 bind 512)
[    0.200000] TCP: reno registered
[    0.210000] UDP hash table entries: 256 (order: 0, 4096 bytes)
[    0.220000] UDP-Lite hash table entries: 256 (order: 0, 4096 bytes)
[    0.230000] NET: Registered protocol family 1
[    0.280000] squashfs: version 4.0 (2009/01/31) Phillip Lougher
[    0.290000] jffs2: version 2.2 (NAND) (SUMMARY) (LZMA) (RTIME) (CMODE_PRIORITY) (c) 2001-2006 Red Hat, Inc.
[    0.310000] msgmni has been set to 26
[    0.320000] io scheduler noop registered
[    0.330000] io scheduler deadline registered (default)
[    0.340000] Serial: 8250/16550 driver, 2 ports, IRQ sharing disabled
[    0.360000] serial8250: ttyS0 at MMIO 0x10000500 (irq = 13) is a 16550A
[    0.370000] serial8250: ttyS1 at MMIO 0x10000c00 (irq = 20) is a 16550A
[    0.390000] ramips-spi ramips-spi.0: master is unqueued, this is deprecated
[    0.410000] m25p80 spi0.0: pm25lq032 (4096 Kbytes)
[    0.410000] 6 cmdlinepart partitions found on MTD device spi0.0
[    0.430000] Creating 6 MTD partitions on "spi0.0":
[    0.440000] 0x000000000000-0x000000030000 : "u-boot"
[    0.450000] 0x000000030000-0x000000040000 : "u-boot-env"
[    0.460000] 0x000000040000-0x000000050000 : "factory"
[    0.480000] 0x000000050000-0x000000130000 : "kernel"
[    0.490000] 0x000000130000-0x000000400000 : "rootfs"
[    0.510000] mtd: partition "rootfs" set to be root filesystem
[    0.520000] mtd: partition "rootfs_data" created automatically, ofs=380000, len=80000
[    0.530000] 0x000000380000-0x000000400000 : "rootfs_data"
[    0.550000] 0x000000050000-0x000000400000 : "firmware"
[    0.570000] ramips-wdt ramips-wdt: timeout value must be 0 < timeout <= 35, using 35
[    0.590000] TCP: cubic registered
[    0.600000] NET: Registered protocol family 17
[    0.600000] 8021q: 802.1Q VLAN Support v1.8
[    0.640000] VFS: Mounted root (squashfs filesystem) readonly on device 31:4.
[    0.650000] Freeing unused kernel memory: 180k freed
[    5.090000] input: gpio-keys-polled as /devices/platform/gpio-keys-polled/input/input0
[    5.190000] Button Hotplug driver version 0.4.1
- preinit -
Press the [f] key and hit [enter] to enter failsafe mode
- regular preinit -
jffs2 not ready yet; using ramdisk
- init -
Please press Enter to activate this console.
[   12.230000] Compat-drivers backport release: compat-drivers-2013-01-08-3
[   12.250000] Backport based on wireless-testing.git master-2013-01-07
[   12.260000] compat.git: wireless-testing.git
[   12.300000] cfg80211: Calling CRDA to update world regulatory domain
[   12.320000] cfg80211: World regulatory domain updated:
[   12.330000] cfg80211:   (start_freq - end_freq @ bandwidth), (max_antenna_gain, max_eirp)
[   12.340000] cfg80211:   (2402000 KHz - 2472000 KHz @ 40000 KHz), (300 mBi, 2000 mBm)
[   12.360000] cfg80211:   (2457000 KHz - 2482000 KHz @ 20000 KHz), (300 mBi, 2000 mBm)
[   12.380000] cfg80211:   (2474000 KHz - 2494000 KHz @ 20000 KHz), (300 mBi, 2000 mBm)
[   12.390000] cfg80211:   (5170000 KHz - 5250000 KHz @ 40000 KHz), (300 mBi, 2000 mBm)
[   12.410000] cfg80211:   (5735000 KHz - 5835000 KHz @ 40000 KHz), (300 mBi, 2000 mBm)
[   13.440000] usbcore: registered new interface driver usbfs
[   13.450000] usbcore: registered new interface driver hub
[   13.460000] usbcore: registered new device driver usb
[   14.640000] PPP generic driver version 2.4.2
[   14.940000] ip_tables: (C) 2000-2006 Netfilter Core Team
[   15.130000] NET: Registered protocol family 24
[   15.160000] ehci_hcd: USB 2.0 'Enhanced' Host Controller (EHCI) Driver
[   16.170000] ehci-platform ehci-platform: Generic Platform EHCI Controller
[   16.190000] ehci-platform ehci-platform: new USB bus registered, assigned bus number 1
[   16.230000] ehci-platform ehci-platform: irq 26, io mem 0x101c0000
[   16.260000] ehci-platform ehci-platform: USB 2.0 started, EHCI 1.00
[   16.270000] hub 1-0:1.0: USB hub found
[   16.280000] hub 1-0:1.0: 1 port detected
[   16.310000] nf_conntrack version 0.5.0 (212 buckets, 848 max)
[   16.640000] ohci_hcd: USB 1.1 'Open' Host Controller (OHCI) Driver
[   16.660000] ohci-platform ohci-platform: Generic Platform OHCI Controller
[   16.670000] ohci-platform ohci-platform: new USB bus registered, assigned bus number 2
[   16.690000] ohci-platform ohci-platform: irq 26, io mem 0x101c1000
[   16.760000] hub 2-0:1.0: USB hub found
[   16.770000] hub 2-0:1.0: 1 port detected
[   16.840000] usbcore: registered new interface driver cdc_acm
[   16.850000] cdc_acm: USB Abstract Control Model driver for USB modems and ISDN adapters
[   17.030000] usbcore: registered new interface driver usbserial
[   17.040000] usbcore: registered new interface driver usbserial_generic
[   17.050000] usbserial: USB Serial support registered for generic
[   17.210000] Linux video capture interface: v2.00
[   17.390000] usbcore: registered new interface driver ftdi_sio
[   17.410000] usbserial: USB Serial support registered for FTDI USB Serial Device
[   17.510000] gspca_main: v2.14.0 registered
[   17.540000] usbcore: registered new interface driver gspca_zc3xx
[   17.580000] usbcore: registered new interface driver uvcvideo
[   17.590000] USB Video Class driver (1.1.1)
[   26.430000] device eth0.1 entered promiscuous mode
[   26.440000] device eth0 entered promiscuous mode
[   26.460000] br-lan: port 1(eth0.1) entered forwarding state
[   26.470000] br-lan: port 1(eth0.1) entered forwarding state
[   28.080000] ramips-wdt: timeout value 60 must be 0 < timeout <= 35, using 35
[   28.470000] br-lan: port 1(eth0.1) entered forwarding state
[   48.100000] jffs2_scan_eraseblock(): End of filesystem marker found at 0x0
[   48.140000] jffs2_build_filesystem(): unlocking the mtd device... done.
[   48.150000] jffs2_build_filesystem(): erasing all blocks after the end marker... done.
[   51.360000] jffs2: notice: (1075) jffs2_build_xattr_subsystem: complete building xattr subsystem, 0 of xdatum (0 unchecked, 0 orphan) and 0 of xref (0 dead, 0 orphan) found.

BusyBox v1.19.4 (2013-04-11 22:01:38 CST) built-in shell (ash)
Enter 'help' for a list of built-in commands.

  _______                     ________        __
 |       |.-----.-----.-----.|  |  |  |.----.|  |_
 |   -   ||  _  |  -__|     ||  |  |  ||   _||   _|
 |_______||   __|_____|__|__||________||__|  |____|
          |__| W I R E L E S S   F R E E D O M
 -----------------------------------------------------
 BARRIER BREAKER (Bleeding Edge, r35407)
 -----------------------------------------------------
  * 1/2 oz Galliano         Pour all ingredients into
  * 4 oz cold Coffee        an irish coffee mug filled
  * 1 1/2 oz Dark Rum       with crushed ice. Stir.
  * 2 tsp. Creme de Cacao
 -----------------------------------------------------
root@OpenWrt:~#

Click above to see flash/boot-log.

Voila, OpenWRT 🙂

This device only has 16 mb of ram and would probably need a ram upgrade to be useful with openwrt. Running luci is insanely slow, so slow that it will drive most people mad. I would rather recommend the TP-Link TL-MR10U. It’s a similar device in the same price range, basically a wr703n with battery – meaning atheros based and 32 mb ram. I didn’t know about the TP-Link at the time when I bought this.

Decoding shellcode

Nasjonal Sikkerhetsmyndighet (NSM) recently put up a few security challenges on their page as part of a hiring, and was linked to by one of the major norwegian tabloids – VG.

Most of them looked like boring substitution cipher and so on.. but one sparked my interrest – shellcode.

31 db f7 e3 68 ff f4 f5 e2 68 fb f5
b0 f8 68 b0 fb fc ff 68 fc f5 e2 f5
68 f5 e2 b0 f6 68 e2 f5 fe f7 68 c6
f9 b0 e4 b9 90 90 90 90 31 0c 04 04
04 3c 1c 75 f7 89 e1 31 c0 b0 04 b2
1c cd 80 b0 01 cd 80

3pq91uIn intel x86 asm opcode 0x31 is a xor, so just based on the first bytes there’s a fair chance this shellcode is intel asm. (also it’s the most common platform.. which makes sense for something like this)

Run it through a disassembler to verify, ndisasm – nasm’s disassembler works great.

; ndisasm -b 32 shellcode
00000000  31DB              xor ebx,ebx
00000002  F7E3              mul ebx
00000004  68FFF4F5E2        push dword 0xe2f5f4ff
00000009  68FBF5B0F8        push dword 0xf8b0f5fb
0000000E  68B0FBFCFF        push dword 0xfffcfbb0
00000013  68FCF5E2F5        push dword 0xf5e2f5fc
00000018  68F5E2B0F6        push dword 0xf6b0e2f5
0000001D  68E2F5FEF7        push dword 0xf7fef5e2
00000022  68C6F9B0E4        push dword 0xe4b0f9c6
00000027  B990909090        mov ecx,0x90909090
0000002C  310C04            xor [esp+eax],ecx
0000002F  0404              add al,0x4
00000031  3C1C              cmp al,0x1c
00000033  75F7              jnz 0x2c
00000035  89E1              mov ecx,esp
00000037  31C0              xor eax,eax
00000039  B004              mov al,0x4
0000003B  B21C              mov dl,0x1c
0000003D  CD80              int 0x80
0000003F  B001              mov al,0x1
00000041  CD80              int 0x80

Short little program. There’s a couple of int 0x80 in there, which usually is a really good indication of linux code – int 0x80 is the interrupt vector used for system calls in linux. There’s a good syscalls reference at: syscalls.kernelgrok.com. Whatever currently in the eax register is used for the syscall, meaning that the two syscalls used in this code is 4 (sys_write) and 1 (sys_exit).

Breaking the code down you find:

00000000  31DB              xor ebx,ebx
00000002  F7E3              mul ebx

; ebx = 0
; eax = eax * ebx = 0

00000004  68FFF4F5E2        push dword 0xe2f5f4ff
00000009  68FBF5B0F8        push dword 0xf8b0f5fb
0000000E  68B0FBFCFF        push dword 0xfffcfbb0
00000013  68FCF5E2F5        push dword 0xf5e2f5fc
00000018  68F5E2B0F6        push dword 0xf6b0e2f5
0000001D  68E2F5FEF7        push dword 0xf7fef5e2
00000022  68C6F9B0E4        push dword 0xe4b0f9c6
00000027  B990909090        mov ecx,0x90909090

; push some data to the stack
; ecx = 0x90909090

0000002C  310C04            xor [esp+eax],ecx
0000002F  0404              add al,0x4
00000031  3C1C              cmp al,0x1c
00000033  75F7              jnz 0x2c

; // Xor the data pushed to the stack with 0x90909090
; while (al != 28) {
;     stack[al] ^= ecx
;     al += 4;
; }

00000035  89E1              mov ecx,esp
00000037  31C0              xor eax,eax
00000039  B004              mov al,0x4
0000003B  B21C              mov dl,0x1c
0000003D  CD80              int 0x80

; // Print stack data to stdout
; sys_write(fd: ebx = 0, *chars: ecx = stack, count: dl = 28);

0000003F  B001              mov al,0x1
00000041  CD80              int 0x80

; sys_exit(1);

So it simply xors some data with 0x90909090 and print the result. Python is pretty great for massaging data like this, especially using their struct module (binary packer/unpacker).

>>> data = [0xe4b0f9c6, 0xf7fef5e2, 0xf6b0e2f5, 0xf5e2f5fc, 0xfffcfbb0, 0xf8b0f5fb, 0xe2f5f4ff]
>>> xordata = map(lambda x: x ^ 0x90909090, data)
>>> import struct
>>> struct.pack('7I', *xordata)

'Vi trenger flere kloke hoder'

While I have no plan of applying, I find small challenges like these (used as a way of sparking interest when hunting applicants) pretty interesting. They have (AFAIK) been pretty popular abroad, but have recently started gaining traction here in Norway as well. Many major webpages have been putting up job offerings as comments in HTML or CSS source files, others have designed challenges like this to attract applicants. The job market here is pretty damn good for technology workers, so maybe it’s a good tactic for seperating yourself as a company from the rest – and at the same time act as a filter for applications.

Liquid Nitrogen Hop Ice Cream

Video

Made hop ice cream with some friends this weekend, using cascade hop. Left hop pellets in milk overnight, filtered out the remains, made ice cream batter the usual way, and then added liquid nitrogen while whisking vigorously.

Ingredients:

  • 3 dl whole milk
  • A couple of hop pellets
  • 2 dl cream
  • 2 eggs
  • 70 g suger
  • 1-2 tablespoons of honey
  • 7 dl liquid nitrogen

Tasted quite bitter (as expected), only the heavy beer drinkers really liked it.

Dead cheap li-ion charger – TP4056

Image

There’s a chip called TP4056 that’s quite good for charging li-ion/li-po cells. You can buy the chip really cheap, or like above – a finished board with usb power in for $1.50 (!) on ebay including shipping. I bought one, soldered on a couple of silicon wires with magnets attached to the end. Also added a plug-able tiny voltmeter (ebay, but this other one from fasttech also looks quite good). I’m not sure how the voltmeter affects the charging (as it feeds off the charging current), but I recon it should be quite fine.

Resistor valuesPer default it uses 1 amp of charging current, which is quite good for large cells, but you can modify it by changing one of the onboard resistors – lower values and you can use it for smaller cells safely.

It’s quite a decent little charger, it manages pretty close to true CC/CV (constant current / constant voltage). It does get a bit hot when charging at 1 amp, especially in the start when the voltage difference between input and output is large, but nothing too worrying.

Termination seems to happen according to spec – just around 4.20 volt.

All in all – quite happy with it. I recon the chip (or even the board) could easily be built into projects that need li-ion/po charging, or even into a battery pack. Can’t beat the price! 🙂