Various services that use SMS notifications or SMS authorization are gaining popularity every day, because it is really very convenient from the point of view of the user and quite safe from the point of view of the developers. Most companies that provide SMS mailing services offer their APIs to implement the sending process (usually HTTP-based), but everyone has a standard connection option - the SMPP protocol. My experience with users of the SMPP protocol shows that they have quite a lot of difficulties. The reason for this (in my opinion) is the thoughtless use of ready-made libraries and, as a result, a complete misunderstanding of what is happening “under the hood”.
In this article I will describe one of the most frequently asked questions from clients - “How to read the text of the incoming message? I found an on-line decoder, but it shows an abracadabra. ” The fact is that some services have not only the ability to send messages, but also receive response messages to them. However, the algorithm described by me is applicable to any action in the SMPP protocol, since in fact, it is an instruction for protocol specification.
Parsing an incoming message without using any SMPP software
We will need:
- SMPP Protocol Specification v3.4
- Wireshark
- Notebook
- Browser
I will not describe the process of getting the cap file itself (dump) SMPP exchange, because There are already many articles on this topic (for example,
this one ).
')
The general procedure for exchanging packets in SMPP is as follows:

As can be seen in the case of an incoming message, we are interested in the package deliver_sm. The package type is determined by the command_id field, which in the case of deliver_sm is 0x00000005 (clause 5.1.2.1 in the specification).
As a result, the filter in wireshark looks like this:
smpp.command_id == 0x00000005
After you have found a packet by filter, copy its contents in HEX format:

The final line to be decoded is:
00000048000000050000000000000003000101636F6F6E6F6C616E642E727500010137393132333435363738390000000000000000
0800000424000c043f044004380432043504424
The item describing the format of the package deliver_sm, in the specification, is 4.6.1 “DELIVER_SM” Syntax. At this point there is a table in which each field of the packet is signed:

Let's start parsing the package.
The first field of the packet,
command_length, is 4 octets in size (size octets column) and type Integer. This means that from the beginning of our HEX line you need to count 4 x 2 = 8 characters.
Why multiply by 2?We copied the string in hexadecimal format which encodes one octet (byte) in two characters.
00 00 00 48 000000050000000000000003000101636F6F6...
(HEX)
00000048 -> (DEC) 72 octets or 144 characters - the length of the entire SMPP packet.
The next
command_id field is the same as 4 octets and Integer.
00000048 00 00 00 05 0000000000000003000101636F6F6...
Let's convert to a readable view: 00000005 = deliver_sm

The
command_status and
sequence_number fields also have 4 octets of each. Where to look at their values, I guess you already guess.
0000004800000005 00 00 00 00 00 00 00 03 000101636F6F6...
The
service_type field may contain a maximum of 6 octets and is of type
C-Octet String . Paragraph 3.1 of the SMPP PDU - Type Definitions states:
C-Octet String ASCII characters terminated with the NULL character
In other words, this is a sequence of ASCII zero octet characters as a field termination character. Those. This field can contain a maximum of 6 characters, but it can be less - the end of this field is designated HEX 00. In this particular example, we immediately see 00 - the field does not contain any value.
00000048000000050000000000000003 00 0101636F6F6...
If this column were filled, then it can be decrypted using a table of ASCII characters.
Skip the next 2 fields
source_addr_ton and
source_addr_npi , since how to decrypt them is already clear and analyze another field with the type C-Octet String - source_addr.
Source_addr may contain a maximum of 21 octets, but in this case it consists of 13 octets including the zero octet which means the end of the field:
63 6F 6F 6E 6F 6C 61 6E 64 2E 72 75
00In the search engine, we make the query “ascii table” and begin to decipher:

63 = c
6F = o
6F = o
6E = n
6F = o
6C = l
61 = a
6E = n
64 = d
And so on until the characters 00.
I also skip the rest of the fields - there are many of them and their definition is no different from the one described above. Let's go to the
data_coding field, without the value of this field, we will not be able to read the message text.
I separated all the fields in the HEX example line, and the data_coding field was in bold and this is what happened:
00000047; 00000005; 00000000; 00000003; 00; 01; 01; 373932393937333630333000; 01; 01; 373932333235303039353900; 00; 00; 00; 00; 00; 00; 00;
08 ; 00; 0424; 000c; 043f04400438043204350442
Clause 5.2.19 of the specification indicates that the encoding is UCS2 (ISO / IEC-10646). (HEX) 08 -> (BIN) 00001000 -> UCS2 (ISO / IEC-10646):

We are looking for a symbol table for: "ucs2 code chart"
043f04400438043204350442
Select the first 2 octets of the text “043f” and search for them on the page.

We continue to allocate 2 octets and search for:
[p] 0440 CYRILLIC SMALL LETTER ER
[and] 0438 CYRILLIC SMALL LETTER I
[in] 0432 CYRILLIC SMALL LETTER VE
[e] 0435 CYRILLIC SMALL LETTER IE
[t] 0442 CYRILLIC SMALL LETTER TE
At this parsing package is over. I hope that the description was clear and fairly complete. In general, if you managed to realize how to read the message, then send it will not be any difficulty. Several fields will change.
Read the specifications - almost everything is already written there.