Hacking the “HAMA” Device.

Posted on 05/01/2010 by

0



This post is about interfacing a strange device. It has two connectors.
1. An European power plug
and
2. A DB-25 Connector.

And I guess you have to connect it to the serial to interface it!…and while plugging it in you have to convert the DB25 to DB9 and put it into the COM2 of an intel FreeBSD machine…and this is what it would look like when you send it!

Example:
#/ FreeBSD: /#
cat /dev/urandom > /dev/cuaa1   #/ cuaa0 for COM1 duh /#
#/ Linux: /#
cat /dev/urandom < /dev/ttyS1

Now…lets find out weather we can output something that makes a lot of sense.
Let the hacking begin!
First of all we have to make a little program to send just a single byte to the serial port…you can do this on a platform: x86/linux.

Example:
root@klendathu:~# dmesg | grep tty
ttyS00 at 0x03f8 (irq = 4) is a 16550
ttyS01 at 0x02f8 (irq = 3) is a 16550A


OK…so now we know which ports to send it to.
Peace of C code:

1
2 #include <stdio.h>
3 #include <unistd.h>
4 #include <sys/io.h>
5
6 #define PORT 0x02f8

7
8 int main(int argc, char *argv[])
9 {
10         ioperm(PORT, 1, 1);             // `man ioperm`
11
12         if(argc>1) {
14         outb(atoi(argv[1]), PORT);              // `man outb`
15         return 0;

16         }
17
18 }
19

When you start to send the bytes…you have to notice the movement of the digits. And only after fiddling with it you will find out the system.

Sending a 4 6 times will result in: 444444__ (The underscore means Void)
The device appears to remember the exact position in which is now 6/8. When we send 6 more times a 5: 55554455 making the position 4/8.

So when you try neither turning it off nor sending the signals to let it forget the position.

Mapping the system

The device has 8 digits + 11 indications of LED’s…You make a loop for your little c code that scans all the combinations. The following patterns would look like this!:

character       byte/code/signal
0               0x0
1               0x1

2               0x2
3               0x3
4               0x4
5               0x5
6               0x6
7               0x7
8               0x8

9               0x9
-               0xa
e               0xb
h               0xc
l               0xd
p               0xe
_ (void)        0xf

led             byte/code range:

0               0x00
1               0x10
2               0x20
3               0x30
4               0x40
5               0x50
6               0x60

7               0x70
8               0x80
9               0x90
10               0xa0

special         byte/code range:
dots            0xb0
no-leds         0xc0

Security Issues
For some reason, sometimes you won’t be able to get the current position of the characters.

For example:
command:                character place:
out port, 0x1           0

out port, 0x1           1
out port, 0x1           2
out port, 0x1           3

When we start the software to send for example the string “__hell0_”:
command:                character place:
out port, 0xf           4

out port, 0xf           5
out port, 0xc           6
out port, 0xb           7
out port, 0xd           0
out port, 0xd           1
out port, 0x0           2
out port, 0xf           3

making the output: “l0___hel”.

If you don’t find a way to avoid this to check the current pointers position…it means no error checking can be done and the device must be manually calibrated.
If there really is no way to check or reset the pointer you could use this for evil purposes. You could go to your local
store/supermarket and send signals to their HAMA devices!


Sourcecode + information sources
The only information source used is the linux and freebsd manual for the I/O c/c++ methods.

Hamahack Source code:

/*
*
*    HAMA shop register-display control code
*    platform: x86/linux, x86/freebsd
*    author: dodo <dodo@darkwired.org>
*    version: 0.2
*    url: http://www.darkwired.org/
*    HAMA article: http://www.darkwired.org/pub/papers/articles/hamahack/
*
*/
#include <stdio.h>
#include <unistd.h>
#ifdef __FreeBSD__
#include<machine/cpufunc.h>
#include<machine/sysarch.h>
#else
#include <sys/io.h>
#endif

#define HAMA_PORT0x02f8
//#define HAMA_PORT0x03f8
#define HAMA_OFFSET_LEFT0x0
#define HAMA_OFFSET_RIGHT0x1
#define HAMAVAL_NUM_PLAIN0x0
#define HAMAVAL_STR_STRIPE0xa
#define HAMAVAL_STR_E0xb
#define HAMAVAL_STR_H0xc
#define HAMAVAL_STR_L0xd
#define HAMAVAL_STR_P0xe
#define HAMAVAL_VOID0xf
#define HAMA_MODE_PLAIN0xc0
#define HAMA_MODES_MAX0xe

typedef unsigned long intulong;
#ifdef __linux__
typedef unsigned short intushort;
#endif
typedef unsigned char uchar;

/* attributes */
signed long int mode = -1;

/* methods */
voidhamaOut(ushort value);
voidhamaPrintLine(char *string, uchar offset);
ushorthamaGetValue(uchar chr);
void hamaIOPerm();

int main(int argc, char *argv[])
{
int i = 1;

/*
if(argc>1) {
hamaIOPerm();
printf("DEBUG!\n");
hamaOut(atoi(argv[1]));
return 0;
}
*/
if(argc>1) {
hamaIOPerm();
if(argv[1][0]=='-') {
mode = atoi((argv[i])+1);
if(mode<0 || mode>HAMA_MODES_MAX) {
printf("error: invalid mode");
return -1;
}
i++;
}
hamaPrintLine(argv[i], HAMA_OFFSET_RIGHT);
return 1;
} else {
printf  (
"usage: %s [ledmode] <string>\n"
"ledmodes:\n"
"-0..%dtoggle different leds on device\n"
, argv[0], HAMA_MODES_MAX
);
return 0;
}

}

void hamaOut(ushort value)
{
#ifdef __FreeBSD__
outb(HAMA_PORT, value);
#else
outb(value, HAMA_PORT);
#endif
}

void hamaIOPerm()
{

#ifdef __FreeBSD__
if(i386_set_ioperm(HAMA_PORT, 0x20, 1)<0)
#else
if(ioperm(HAMA_PORT, 1, 1)<0)
#endif
{
printf("error: could not get IO permissions\n");
exit(-1);
}
}

void hamaPrintLine(char *string, uchar offset)
{
int i, value;

switch(offset)
{

case HAMA_OFFSET_LEFT: {

for(i=0; 8>i; i++) {
if(strlen(string)>i) {
value = hamaGetValue(string[i]);
} else {
value = hamaGetValue(' ');
}

hamaOut(value);
/* for some reason, we need to sleep a little */
usleep(50);
}

break;
}

case HAMA_OFFSET_RIGHT: {
for(i=7; 0<=i; i--) {
if(strlen(string)>i) {
value = hamaGetValue(string[(strlen(string)-1)-i]);
} else {
value = hamaGetValue(' ');
}
hamaOut(value);
/* for some reason, we need to sleep a little */
usleep(50);
}
break;
}
}

}

ushort hamaGetValue(uchar chr)
{
ushort value = HAMAVAL_VOID;

if(chr >= 0x30 && chr <= 0x39) {
value = (chr-0x30);
} else {
switch(chr)
{
case '-': value = HAMAVAL_STR_STRIPE; break;
case 'e': value = HAMAVAL_STR_E; break;
case 'h': value = HAMAVAL_STR_H; break;
case 'l': value = HAMAVAL_STR_L; break;
case 'p': value = HAMAVAL_STR_P; break;
case 'E': value = HAMAVAL_STR_E; break;
case 'H': value = HAMAVAL_STR_H; break;
case 'L': value = HAMAVAL_STR_L; break;
case 'P': value = HAMAVAL_STR_P; break;

/* l33t H4X0Rz */
case 'o': value = 0x0; break;
case 'i': value = 0x1; break;
case 'O': value = 0x0; break;
case 'I': value = 0x1; break;

}
}
if(mode==-1) mode=0xc;
return (value+(mode*0x10));
}

Cheers! 🙂

Advertisements