Man in the middle-ish?

Hi all,

I was wandering for a while now (probably about two years now), IF it would be possible to have something like a “man in the middle attach” (minus the attack, kinda).
So after seeing the M2, the first thing i thought is if we can use a dual end OBD (one side connects to vehicle, other side has two ODB ends, like this) and get a somewhat of a man in the middle attack.

The main focus here is not only to see what is the vehices CAN traffic, but also to get a better understanding on how an ELM OBD reader for example, works.

This will give a better understanding over, CAN messages and commands, thus maybe assisting better on writing your own script.
I am positive that, many ODB bluetooth/phone readers out there, have used probably an arduino or a Pi with a CAN shield, to do this very same procedure and create apps (most of them aiming at a specific vehicle brand).

So, is it possible? Would be quite interesting to me at least, not only as CAN penetration testing and injecting data, but also software reverse engineering/developing wise.

Thanks in advance.

For sure it’s possible. People do it all the time. This is one of the best ways to figure out an OEM interface. You connect the OEM tool up to the OBDII port along with your capture hardware - both on the Y adapter. Now your capture tool can see everything that both sides are doing.

1 Like

Thanks @CollinK . I will sure give it a try as soon as i get my Y adapter i ordered.

Very looking forward to sniff some traffic with this.

But would it be possible to use the 26pin connector on the M2 to setup an OBD there, which will then set the M2 to act as a true man in the middle (since it will be in the middle of scanner and OBD of vehicle)?
Could the communications be fine to scanner and vehicle, while M2 stores all sorts of info into SD???

That would be pretty interesting.
Doable? Or the 26pin will not process communications to the front OBD port?

With the M2, if your doing CANBUS stuff you can use the 2 CANBUS ports. If you are doing GM’s SWCAN you can use one of the CANBUS ports and the SWCAN port.

I THOUGHT there was a bridge mode available on the CANBUS ports but @CollinK would have to chime in on that.

I hope to have a method of tying two M2’s together sometime soon but due to school work and actual work I have had little spare time to work on this right now. In my method two M2’s will talk to each other using the UART in the expansion port and will be able to syncronize between any two protocols supported by the units. You will be able to do a MIM type setup with this and log what is coming from which side syncronized to insure you are getting the information in sync.

Again this is not working yet and I have not spent much time with it yet. I will likely be spending a large part of my summer vacation working on this stuff.

Rodney

Using 2 can buses on the OBD is fine for separating the messages but makes it very difficult to follow the conversation of the 2 devices (Car and OBD device). I’ve done lots of this and it’s best to just log both at the same time. It’s easy to figure out which side is which by the ID’s and messages.

By doing this I was able to follow an all error’s clear sent to the car and programmed a dongle to replicate it.

Here is a good example of man in the middle though. I was asked if I could change the VIN number being reported to an Audi MIB unit. With the massive amount of messages on the new Infotainment bus on Audi’s I had to get M2 to handle it. The regular Arduino’s with CAN just aren’t fast enough to make changes and not loose any messages.

Here is some pictures to see the before and after


Note there are multiple messages for the VIN that have to be altered so it was fun figuring this out for the first time but now I should be able to do some other cool stuff.

P.S. I don’t use Arduino for CAN sniffing I have PCAN-USB Pro FD and Kvaser Can Leaf for that.

Anyone have an example sketch for this application?

I want to put the M2 in between the CANBUS going to the instrument cluster and pass along all messages except the CEL. Maybe also control the MPG readout.

My car doesn’t use CANBUS for everything and I don’t have to pass all the messages to the instrument cluster, so I think one M2 could handle it.

The closest thing I have to what you want is here:

If you have the due_can library (and you need it if you’re going to do CAN with the M2) then you already have this in the examples folder. You can modify it to drop certain frames. It’s already set up to pass through traffic both ways.

2 Likes

Thank you! I figured it wasn’t too complicated I just didn’t know where to look.

I think I can easily modify that to do exactly what I want.

Sorry for what is probably a dumb follow up question.

Even though that sketch is called “CAN_TrafficModifier.ino” as far as I can tell it only reads CAN0 and forwards it to CAN1, and vice versa.

Can you show me what dropping or modifying a frame before forwarding it would look like? Thanks again.

Mate, that is an excellent job you have done right here.
This is some good reverse engineering.

Still though, didn’t you have the component protection active on this?
Also the navigation maps seed key did not change??? Or are the VAGs deferent than what BMW does? I know BMW seed keys for FSC (map activation) changes depending to VIN and also become unusable once the VIN is changed. You can only use them once the “original” VIN is returned back to its place.

I would be really interested if you could PM me on how you did this, or even share it here.
VEEEEEERRRRRRYYYYYY interesting stuff right here. :slight_smile:

You’re right. I don’t know why it doesn’t modify traffic… whoops… I’ve committed a quick fix for that.

Basically, you can just edit the incoming frame then send it back out. If you get a frame into a variable called canFrame and you want to make the first byte 0x13 then you’d do

Can0.read(canFrame);
canFrame.data.bytes[0] = 0x13;

Then send it back out immediately (can be on the same bus it came from if you’d like)

Can0.sendFrame(canFrame);

You can find the various parts of the CAN_FRAME struct in can_common.h:

typedef union {
  uint64_t value;
	struct {
		uint32_t low;
		uint32_t high;
	};
	struct {
		uint16_t s0;
		uint16_t s1;
		uint16_t s2;
		uint16_t s3;
  };
	uint8_t bytes[8];
	uint8_t byte[8]; //alternate name so you can omit the s if you feel it makes more sense
} BytesUnion;

typedef struct
{
  uint32_t id;		// EID if ide set, SID otherwise
  uint32_t fid;		// family ID
  uint8_t rtr;		// Remote Transmission Request
  uint8_t priority;	// Priority but only important for TX frames and then only for special uses.
  uint8_t extended;	// Extended ID flag
  uint16_t time;      // CAN timer value when mailbox message was received.
  uint8_t length;		// Number of data bytes
  BytesUnion data;	// 64 bits - lots of ways to access it.
} CAN_FRAME;
1 Like

Thank you for the fix!

I logged the following yesterday and I think it is the message I need to change.

ID: 0xC0 Len: 2 Data: 0xBA 0
ID: 0xC0 Len: 2 Data: 0xDA 0

If I change the code to what’s shown below, would it modify ID 0xC0’s data from 0xBA to 0xDA and forward it to CAN1? I don’t need to modify it going the other direction, in this case.

void loop(){
  CAN_FRAME incoming;

  if (Can0.available() > 0) {
	Can0.read(incoming);
	   if (incoming.id == 0xC0) {
	      incoming.data.bytes[0] = 0xDA;
       }
	Can1.sendFrame(incoming);
	//printFrame(incoming);  //uncomment line to print frames that are going out
   }
  if (Can1.available() > 0) {
	Can1.read(incoming);
	Can0.sendFrame(incoming);
	//printFrame(incoming);
  }
}

Yes, that would forward traffic through but modify any frame with ID 0xC0 to have its first byte be 0xDA. This will happen universally though. If the first byte was really 0x36 it’ll still get turned into 0xDA. You can add an additional if to make sure you only change 0xBA to 0xDA if needed. But, it might not be necessary.

1 Like