Tuesday, October 20, 2020

kernel Lockdown

No more easy tasks during the "kernel Lockdown"

No more easy tasks during the “kernel Lockdown”

Today I wanted to show my Exein fellow how to extract a standard x86_64 Bios image from a live PC.
Quite easy and common task that should not have any issue.
So I triggered the dd command to accomplish the task:

sudo dd if=/dev/mem of=bios.rom bs=64k skip=15 count=1

No problem was expected; still something weird caught my attention:

$ sudo dd if=/dev/mem of=pcbios.rom bs=64k skip=15 count=1
dd: failed to open '/dev/mem': Operation not permitted

Investigating on the issue, it came out that a reasonably new LSM was acting behind the scenes preventing me from accomplishing the easy task I wanted to do.

$ sudo cat /sys/kernel/security/lockdown 
none [integrity] confidentiality
$ dmesg
[    0.000000] Kernel is locked down from EFI Secure Boot mode; see man kernel_lockdown.7
[...]
[    0.787348] Lockdown: swapper/0: hibernation is restricted; see man kernel_lockdown.7
[...]
[   21.638946] Lockdown: systemd: /dev/mem,kmem,port is restricted; see man kernel_lockdown.7
[...]
[   24.578882] Lockdown: Xorg: raw io port access is restricted; see man kernel_lockdown.7
[...]
[   26.249451] Lockdown: systemd-logind: hibernation is restricted; see man kernel_lockdown.7
[...]
[   26.254389] Lockdown: systemd-logind: hibernation is restricted; see man kernel_lockdown.7
[...]
[  921.376121] Lockdown: dd: /dev/mem,kmem,port is restricted; see man kernel_lockdown.7

Now the question is, what this Lockdown is, and what is it doing on my PC.
According to LWN, Lockdown is a new way to keep the kernel secure from cyber-attacks, which is part of the Linux kernel starting from Aug 20, 2019, when the commit 000d388ed3bbed745f366ce71b2bb7c2ee70f449 integrated it within the official main branch of the Linux Kernel.

This was the 5.4-RC1 version.
What exactly does this Lockdown restrict?
First off, it will restrict access to kernel features that may allow arbitrary code execution, block processes from reading/writing to /dev/mem, and /dev/kmem memory, and /dev/port.
Other features include:

  • Enforcing kernel module signatures.
  • Prevents even the root account from modifying the kernel code.
  • Kexec reboot.
  • Restrict the use of hardware that could potentially generate direct memory addressing (DMA).
  • Restrict the use of KDADDIO, KDDELIO, KDENABIO and KDDISABIO console ioctls.

There are two modes available to the Lockdown module: Integrity and Confidentiality. When in Integrity mode, kernel features which would allow userland code to modify the running kernel are disabled. When in Confidentiality mode, userland code to extract confidential information from the kernel will be disabled.
At the end of the day, Lockdown is installed by default on many Linux distributions, including the one I was using.

This also means, It is like I can not dump the BIOS right now.

Now let’s see what can be done to disable it.
Where to start, the kernel log mentioned kernel_lockdown.7; let’s start from here!

Quick note: the distro I am using, Linux Mint 20 does not include the mentioned man page.

Sure, I can find it on the internet; for example, here is the man page mentioned in the kernel logs.

According to this source and others I found on the internet, there’s no way to disable Lockdown LSM but by being at the main console and pressing a SysReq combination: “SysReq+x”.

Trying to do what is suggested, nothing happened, and looking in the kernel message log, the following message appeared:

sysrq: HELP : loglevel(0-9) reboot(b) crash(c) terminate-all-tasks(e) memory-full-oom-kill(f) kill-all-tasks(i) thaw-filesystems(j) sak(k) show-backtrace-all-active-cpus(l) show-memory-usage(m) nice-all-RT-tasks(n) poweroff(o) show-registers(p) show-all-timers(q) unraw(r) sync(s) show-task-states(t) unmount(u) force-fb(V) show-blocked-tasks(w) dump-ftrace-buffer(z)

which in turn indicates the combination has not been implemented.
Investigating on this latter, more obscure scenario is shown; in the Linux Kernel source tree, as far as the last available Linux Kernel version (5.9.1), there’s no evidence this combination has been ever implemented.

*sysrq_key_table[36] = {
[...]
        &sysrq_showstate_blocked_op,    /* w */
        /* x: May be registered on mips for TLB dump */
        /* x: May be registered on ppc/powerpc for xmon */
        /* x: May be registered on sparc64 for global PMU dump */
        NULL,                           /* x */
        /* y: May be registered on sparc64 for global register dump */
        NULL,                           /* y */
        &sysrq_ftrace_dump_op,          /* z */
};

Further investigations have shown that the mentioned feature has indeed been proposed, but it has not yet been merged with the main branch.

Looking carefully at the official Linux kernel code, another fact is realized:
There’s not even a location within the official Linux Kernel source tree that changes the kernel_locked_down, the variable that keeps the LSM status.
This leads to another question: why the Lockdown is enforced on my PC?
Reading at the Kernel log messages, one of the very first lines suggest the cause…

[    0.000000] Kernel is locked down from EFI Secure Boot mode; see man kernel_lockdown.7

Looking at the message text, it can be guessed that a call to lock_kernel_down("EFI Secure Boot mode", LOCKDOWN_INTEGRITY_MAX) may have this message generated, but it is not yet clear where this call has been issued. Considering the message timestamp, it appears clear that it must be an early just after the kernel takes the control.
The function setup_arch(char **cmdline_p) in the /arch/x86/kernel/setup.c file seams to be a perfect fit for this call. Investigating on this direction, another patch can be found on the internet.

Situation now is that Linux Mint 20, but also Ubuntu 20.04 are using a Linux Kernel with an unofficial patch for implementing the Secure Boot Lockdown trigger, but they do not bother to implement any unofficial mechanism to disable the Lockdown if needed.
Why has this happen is not known, but many discussions can be found on the necessity EFI Secure boot to enable the Kernel Lockdown. LWN, Linux Journal, Linux GIT
Back to the main topic, read /dev/mem, please note that Lockdown do not expect to reduce the Lockdown level.

static int lock_kernel_down(const char *where, enum lockdown_reason level)
{
        if (kernel_locked_down >= level)
                return -EPERM;

        kernel_locked_down = level;
        pr_notice("Kernel is locked down from %s; see man kernel_lockdown.7\n",
                  where);
        return 0;
}

So the fact is that at this moment, I can do nothing to read the Bios and show my colleague how easy it can be doing such a thing.

Am I still sure it is easy?!

That’s what brought me to the following solution to decrease the Lockdown level.

To compose a solution I’ve been through a few issues:

  • The symbol kernel_locked_down is not exported.
  • Starting from Kernel 5.7 kallsyms_lookup_name, a function that does the essential task of looking for unexported symbols, is no more exported.
  • Due to the fact that Kernel Lockdown level is LOCKDOWN_INTEGRITY_MAX, install unsigned modules is restricted.

Sunday, October 2, 2016

RS-485 Anti-theft system commands

Some of you may have read on of my previous post, where I tried interpret the keypad print command.
If you did, well some of the interpretations I wrote on it were wrong.
This post is the second attempt to interpretate the dialogue exchanged between main board and the keypad.

After some researches and tests, I came out with the following, which if it is not the correct frame format, it is very close to it.


Each device connected to this bus, seems to follow this rule in the format of the frames produced.


Length is the first byte of each frame. It appears to be one byte long, which also means that a frame cannot be larger than 258 bytes including the length and checksum bytes. This does not seem to be a problem, all traffic I watched, no frame was longer than 25 bytes.


ADDR is the layer level address of the device. Few facts I noticed about the ADDR field:
  • The address 0x00 seems to be reserved to the main board. All devices, when queried, simply answers to this address.
  • Keypads are ranged from 0x10 to 0x1f (on the PCB of each device there are 4 deepswitch which can be used to select the low order four bits). The master keypad on the actual system must be the 0x10 address. In fact main board appears to send bytes directly to this address during normal operation.
  • The RFID readers seem to be ranged at 0x50 and 0x5f.
  • It seems there is some sort of multicast address ranged probably from 0xf0 to 0xff, not clear how does this work, but when mainboard starts, it seems to query 0xff. It also appears that 0xfe must be some sort of multicast directed to keypads. The keypad I have does not seem to recognize this kind of addresses btw.
CMD is the place where you tell to the addressed device what you want. Every device has its own mapped functions. No need to be discussed in this section.

DATA is the field where, if needed, the command data is placed. Not all commands have data, and if data is needed, it depends from the command.

Checksum is where a redundancy code is calculated to guaranty the integrity of the frame. The checksum is calculated on all the frame excluded the length field which is not included in the sum. Also I determined that this particular checksum can be calculated adding all bytes in a 16 bit integer and then checksum the 16 bit accumulator into a 8 bit value. eg. this frame tells a keypad to print "Hello World!" string in the upper line of the display. 1310140048656c6c6f20776f726c64212020202006 checksum is the last byte of the string an is calculated as: 
16bitsum(10+14+00+48+65+6c+6c+6f+20+77+6f+72+6c+64+21+20+20+20+20)=0501
8bitsum(05+01)=06

Thursday, September 29, 2016

Keypad print string command

( Warning this is an early examination and interpretation of the data, some of the deductions I made are not accurate)
This is the first of a series of posts, where I'll try examine the list of commands I logged from a dialogue between the keypad and the mainboard.

Here the first: Print on display

A stream starting with the byte 0x13 seems to have the means of "print command".
This command seems to have a fixed length of 21 bytes.



Command example:
The following sequence prints on screen starting on top left: “Hello world!”
1310140048656c6c6f20776f726c64212020202006

0x13 print command
0x10 address of the first keyboard on the bus.
0x14 Unknown at the moment, but it must be present
0x00 the position 0x00 on the display, which means corner top – left
0x48,0x65,..,0x64,0x21,0x20,0x20,0x20,0x20 “Hello world!    ” 
0x06 checksum: 10+14+00+48+65+6c+6c+6f+20+77+6f+72+6c+64+21+20+20+20+20=>0501=>05+01=06

Anti-theft system keypad


In this post I want to log my experience in reverse engineer the protocol used in ROKONET and possibly other manufacturers' anti-theft system peripherals.

Somewhere in the past I bought an anti-theft system for my home, but because I'm a systems nerd, I chose one which claims it can be interfaced with computers in a computers network.
Unfortunately, what I got after my purchase, was very different from my expectations!
 
I got a closed system which could be configured through an IP network using its manufacturer's proprietary software running only under MS-Windows. If this was not enough, manufacturer won't assist end-users, that because the system is not meant to be installed or configured by the end user, but it have to be installed and configured only by manufacturer authorized personnel. However, if enduser wants, he can buy it and then arrange himself a solution.Very disappointing.

In spite this system cost me good money, it remained in a dusty drawer for a long time, until I found the time to work on it.
Now I'm here logging my progresses on this matter and sharing them with the world, hoping those can be useful to someone other than me.

The big picture is to open the anti-theft systems to the world of the open source, letting open source software such as Asterisk, Motion, Zone Minder and guess you what, integrates with proprietary hardware such as keypads, RFID scanners, PID sensors, proximity sensors, and other anti-theft systems specific hardware.

I'm still far from the target, but at least let dreams fly high!

Back on Earth,  let's start with something, let's start with a keypad, the most common piece of hardware every anti-theft system should have.


Manufacturers divide peripherals in two main classes: dumb and intelligent. To "dumb" class belong for example sensors such as PID, contacts and all the sensors which communicates with just a open-closed contact communication. Intelligent ones such as keypads, RFIDs and audio systems use so called "BUS" for connecting the main board of the system.

Keypads belong to the latter class so the first step is to identify what this, so called "bus", actually is.

BUS is a 4 wires line which connect more than one peripheral to the main board of the system.
Usually these 4 wires have a fixed color scheme, which is RED, BLACK, YELLOW and GREEN.
This color scheme is wide spread among vendors and manufacturers, and it seems to be a de facto standard among anti-theft system.
Hypothesis is that this so called BUS is nothing more than an half-duplex RS-485 implementation and a couple of wires with power supply.
A close look at the circuitry seems to confirm this hypothesis.
You can see on the board distinctly the RS-485 driver SP485EC which connects directly to the keypad MCU UART pins.
Looking at the RS-485 input circuitry, you can find two of the best practise the rs-485 designer have published: fail safe resistors (a pull-up and a pull-down resistor) and two diodes operating as transient overcurrent protections.

It is now important to familiarize with the data passing over this connection.
To do this, my first guess has been trying to sniff the data on the wires.
A simple guess (9600,8,n,1) of the serial settings an I had a dump of bytes main board and keypad are exchanging.
Beware, the fact that you can read from a serial stream, and that data you read is meaningful or correct, DOES NOT mean you have the correct serial setting.
At the time I didn't know this detail yet, and it cost me several hours struggling on why I couldn't transmit anything to the keyboard.

Here you can see a comparison between my generated message (bottom), and the same  generated by the original main board (upper).
Several hours later, I finally found that this particular setup wants a serial setting with 2 stop bits, which means 9600,8,n,2 and not 9600,8,n,1.

Another problem is that sniffing from an half duplex dialogue made on the same pair, gives you a detailed list of bytes exchanged, but doesn't give you any information about direction of those bytes, nor the timing.
Sniff data on the UART pin on the MCU gave me a better understanding fo that dialogue.
Using this I finally could get a precise list of messages exchanged between main board and the keypad.
Here for you an piece of the message exchanged between those two. I indicated with *xxx* messages originated by the keypad.



02ff0404
02101a2a                                                   *0200a3a3*
0310058095                                                 *02002323*
02030407
02050409
02500454
0285078c
020a040e
03fe168095
13fe140050524f4752414d4d415a494f4e453a209c
13fe1410534953542e204e4f4e2050524f4e544fa5
02fe1a19
02101a2a                                                   *02002323*
031019022b                                                 *02002323*
041022031146                                               *02002323*
041018000028                                               *02002323*
131014000000000000000000000000000000000024                 *02002323*
131014100000000000000000000000000000000034                 *02002323*
0310160026                                                 *02002323*
02030407
02050409
02500454
04850f01099e
0285078c
020a040e
03fe168095
13fe140050524f4752414d4d415a494f4e453a209c
13fe1410534953542e204e4f4e2050524f4e544fa5
02fe1a19
02101a2a                                                   *02002323*
041022031146                                               *02002323*
02030407
02050409
02500454
04850f01099e
0285078c
020a040e
03fe168095
13fe140050524f4752414d4d415a494f4e453a209c
13fe1410534953542e204e4f4e2050524f4e544fa5
02fe1a19
02101a2a                                                   *02002323*
04101820236b                                               *02002323*
1310140050415254495a494f4e45203120202020fd                 *02002323*
1310141020202020414c4c41524d45202020202055                 *02002323*
03101680a6                                                 *02002323*

Thursday, September 8, 2016

Cisco 3500 XL fan subsystem failure.

It is quite old, yet still useful. I'm talking about an old Cisco 3500 XL series switch, I use every day in the lab of the company I work to. I don't want to talk about all the good points this switch has, but rather I'd like to talk about a failure it had, after almost 20 years it worked continously.
After all this years it broke its fan system.
It's summer, and if I want it last other 20 years, I had to fix it somehow.
The very first thing to do is understand how fan subsystem works.
Not the hardest task in the world, you just need to follow the tracks on the PCB from fan backwards to components.

Doing this you you'll identify the two main components the subsystem:
HP4410D: the  MOSFET used to command the power 5V circuit
TC648: the fan speed PWM controller.

One of those twos must be the broken one.
Roughly, the fan subsystem should look something like:

Both devices are packaged into a SOIC8 package, people skilled more than I am, are able to remove this package without damage the PCB nor the component using just iron. About me, I'm not that good and I had to use my cheap rework station.
Once the PWM controller is removed, it is possible to probe Vin. By using the TC648 datasheet you know that at this point tension should range from 1.25V to 2.65V, according to enviroment temperature.
In my case it was 2.4V which is a resonable.
With TC648 removed, the base of the mosfet is exposed to manual drive, I could therefore short Vout to Vdd and GND and observe fan spin at maximum rate, and fan to stop when Vout is put to GND.
This leaded me to the conclusion that  the MOSFET HP4410D had to be ok.
As counterproof, test the TC648 was a little more difficult since its package is not breadboard friendly.

Using this I could be sure the TC648 was broken, and than changing it I could fix my switch.
I hope someone else could found this article useful.





Wednesday, December 30, 2015

Fiat Panda windscreen wiper timer

My Panda, after almost 16 years of service, begins to show its years.
This time, the front  wiper does not work properly.
You may read almost evreywhere, Google is your friend....
About this matter, it seems nobody ever went deeper, and to my issue, which seems to be quite widespread, Google wouldn't helped that much; the only answer I found by it is "change the motor and its controlling circuit". This solution can be quite expansive, looking around for prices,  it seems you can not find it for less than 100€.
On the other hand, looking at the controlling circuit, it does not seem to be very complicated, so I decided to use some time to resolve my issue, and therefore save 100€.



As from the image I included in this post, circuit itself is not too complicated.
I also made some schemas to help myself in understanding its behaviour.

The switch appearing in the bottom of the schema, is embedded in the gear inside the transmission of the motor. Its rotation make the controller understand about the wiper position. It is a plastic gear with the core made of conductor material. It appears as follow:
Where the RED part is the metallic core, and the black lines is where contact from the control circuit goes.

Well, I guess this is the time where I tell you which is my problem, after all.
Problem is as follow:  the "SLOW" speed of the wipers does not work, and when it is set to the "FAST" speed, if you turn off the wiper it stops where it is, without return to its home postion.
After several hours of analysis, I found where the problem lies.
It is due to the oxidation of the normally open contact of the relay.





This way I saved myself more than 100€ for the spare part, I hope anyone else could found my info useful and save his money.

Friday, December 11, 2015

Block aggressive advertising calls

In my country, but I bet anywhere else do the same, the telephone calls for proposing new products are constantly increasing, these annoying calls, sometimes malicious, aren't always welcome.

My country has adopted a kind of institutional way to handle this phenomena, it is called  "registro pubblico delle opposizioni", using this, any citizen may publish his telephone number, merely this action should him guarantee he would never ever receive again any advertisement call.

Unfortunately, reality can't be more distant from what really is going to happen.

Telephone spammers do not use to follow rules, and the weak statement "this user does not want to be called for commercial purposes "  is not enough to prevent they to call you. 

If you do not want to be called, you have to find yourself a way to do that.
In other words, you have to find a way to recognize them as spammer, and forward them, for example, to an announce stating you do not want to be called.

As an Asterisk user I have a framework at my disposal, which potentially lets me route calls using any sort of policy; but the main issue is how to identify a spammer?

Internet community, seems to have faced this problem and has built a kind of database in which people complaints about telephone numbers.

It exists, for example, a service called TELLOWS on which anyone can leave a comment on a source telephone number.

So why don't use those information to identify spammers and avoid unwanted telephone calls?

My proposal is integrate the service provided by TELLOWS in the Asterisk dialplan.

Here an example of my thougths.

in the Asterisk dialplan
exten =>  incoming,       1,              Noop(Incoming call is just arrived)
exten =>  incoming,       n,              Set(tellowsc=${SHELL(tellows_c.sh ${CALLERID(num)})})
exten =>  incoming,       n,              GotoIf($[${tellowsc}>1]?reject)
exten =>  incoming,       n,              Dial(${destination},30,${FLAGS})
exten =>  incoming,       n,              HangUP()
exten =>  incoming,       n(reject),      Answer()
exten =>  incoming,       n,              Wait(2)
exten =>  incoming,       n,              Set(CDR(userfield)=RejectedByPolicy)
exten =>  incoming,       n,              Playback(spam)
exten =>  incoming,       n,              HangUP()
the bash script for the italian version of TELLOWS
#!/bin/sh
score=$(wget -O - -q "http://www.tellows.it/num/$1" | grep "/images/score/score[0-9].png" | grep scoreimage | sed -r 's/.*score([0-9])\.png.*/\1/');
comments=$(wget -O - -q "http://www.tellows.it/num/$1" | grep "itemprop" | grep "Numero di commenti:"| sed -r 's/.*>([0-9]+)<.*/\1/');
echo -n "$comments";
I used, to reject calls, the number of comments the number has, but there's also a kind of number score, you can use to take your decision