Reversing hash, Finding collision (XOR with sums and left/right shifts) - c++

A ^ ( (A >> 2) + (A << 5) + C ) == B
How to find A if B is const and C is variable? (C can be changed if there is no solution with it)
A is DWORD, B is DWORD, C is BYTE != 0
Edit1: after GalacticJello's answer, I've got another question: is there any way to do it without a loop (simplifying the expression)?
Why do I need this:
I am trying to make a reverse function (collision searcher) for
unsigned int X(const char* const in) { //strlen(in) is always < 127
unsigned int result = 0x12345678; //just for an example
for(int i = 0; in[i] != 0; ++i)
result ^= (result >> 2) + (result << 5) + in[i];
return result;
}
Currently I have a loop that generates random C and then searches A.
(I search A using a loop that generates a random value [for A] and checks if the above expression is true)
Edit2: This is my current code for searching collisions, that I am testing now..
#include <stdio.h>
#include <conio.h>
using namespace std;
unsigned int originalHash(const char* const in) {
unsigned int result = 0x12345678;
for(int i = 0; in[i] != 0; ++i) {
result = result ^ ((result >> 2) + (result << 5) + in[i]);
}
return result;
}
//A ^ ( (A >> 2) + (A << 5) + C ) == B
bool findSolutions(unsigned int inHash, char* _C, unsigned int* _A) { //Starts searching from *A and *C and writes there values on success.
unsigned int C = *_C;
if(C == 0) ++C;
unsigned int A = *_A;
for(C; C < 256; ++C) {
for(A; A < 0xFFFFFFFF; ++A) {
if((A ^ ( (A >> 2) + (A << 5) + C )) == inHash) {
*_C = C;
*_A = A;
return true;
}
}
A = 0;
}
return false;
}
bool findCollisions(unsigned int inHash, char* szOutStr) {
const unsigned int REQ_HASH = 0x12345678;
unsigned int prevHash = 0;
int curChar = 0;
do {
printf("Loop Begin:\tI = %i | H = %08x | rH = %08x\n", curChar, inHash, REQ_HASH);
if(!findSolutions(inHash, &szOutStr[curChar], &prevHash)) {
printf("Unable to find solutions for %08x\n", inHash);
if(curChar == 0) return false;
--curChar;
continue;
}
if(prevHash == REQ_HASH) {
szOutStr[curChar] = 0;
return true;
}
printf("Found solution:\tC = %02x (%c) | A = %08x\n", szOutStr[curChar], szOutStr[curChar], prevHash);
char firstSolutionC = szOutStr[curChar];
unsigned int firstSolutionA = prevHash;
printf("Trying to find alternative solutions..\n");
do {
if(!findSolutions(inHash, &szOutStr[curChar], &prevHash)) {
printf("Alternative solution not found!\n");
break;
}
printf("Alternative solution found [%s valid]:\tC = %02x (%c) | A = %08x\n", prevHash == REQ_HASH ? "" : "not", szOutStr[curChar], szOutStr[curChar], prevHash);
if(prevHash == REQ_HASH) {
szOutStr[curChar] = 0;
return true;
}
++prevHash;
} while(true);
szOutStr[curChar] = firstSolutionC;
prevHash = firstSolutionA;
printf("Using first solution:\tC = %02x (%c) | A = %08x\n", szOutStr[curChar], szOutStr[curChar], prevHash);
++curChar;
inHash = prevHash;
} while(curChar < 127);
return false;
}
int main(void) {
char mask[] = "hQh";
DWORD original = originalHash(mask);
printf("%s == %08x\n", mask, original);
char out[128];
memset(out, 0, sizeof out);
if(findCollisions(original, out))
printf("%08x == %s\n", original, out);
else
printf("Unable to find collisions\n");
getch();
return 0;
}

I'm just going to take a stab at the question (sorry for the C# code, but you should be able to get the gist):
A ^ ( (A >> 2) + (A << 5) + C ) == B
static List<Tuple<uint, uint>> FindSolutions(uint B)
{
var solutions = new List<Tuple<uint, uint>>();
for (uint C = 0; C < uint.MaxValue; C++)
{
for (uint A = 0; A < uint.MaxValue; A++)
{
uint guess = A ^ ((A >> 2) + (A << 5) + C);
if (guess == B)
solutions.Add(new Tuple<uint,uint>(A, C));
}
}
return solutions;
}
var solutions = FindSolutions(0x00000001);
If B is your constant (0x00000001 in this case), then the first few solutions for A and C are:
A = 0x8b439581, B= 0x00000001, C = 0x00000000
(0x8b439581 ^ ((22d0e560) + (6872B020) + 0)) == 0x00000001
0x8b439581 ^ (0x8b439580) == 0x00000001
0x00000001 == 0x00000001
others:
A = 0x9ba5e354, B= 0x00000001, C = 0x00000000
A = 0x00000000, B= 0x00000001, C = 0x00000000
A = 0x6a7ef9db, B= 0x00000001, C = 0x00000004
... etc.
EDIT:
To find collisions, you can simply perform a brute force through the keyspace.
Again, sorry for the C# code:
static uint originalHash(string input)
{
unt result = 0x12345678;
for (int i = 0; i < input.Length; i++)
result ^= (result >> 2) + (result << 5) + input[i];
return result;
}
var charset = new string(Enumerable.Range(1, 255).Select(i => (char)i).ToArray());
var hits = new List<string>();
var hashToFind = originalHash("hQh");
for (int wordNum = 1; wordNum < int.MaxValue; wordNum++)
{
var word = Utils.NumberToString(wordNum, charset);
var guess = originalHash(word);
if (guess == hashToFind)
{
Console.WriteLine("Found: " + word);
hits.Add(word);
}
}
Running the above code gave me the following collisions after a minute or two:
cê cë1 côÌ cõí cö c÷¦ cøG cùh dÌ1 dÍ dÒí dÓÌ dÖh d×G dئ dÙ e¬
e­1 e²Ì e³í e¶G e·h e¸ e¹¦ f1 f f¦ f fh fG fí fÌ gm gn1
gq gr¦ gsG gth gwÌ gxí hO1 hP hQh hRG hS¦ hT hUí hVÌ i/ i01 i1G
i2h i3 i4¦ i5Ì i6í
Those don't translate well, here's the byte values:
{ 0x63, 0xEA, 0x10, }
{ 0x63, 0xEB, 0x31, }
{ 0x63, 0xF4, 0xCC, }
{ 0x63, 0xF5, 0xED, }
{ 0x63, 0xF6, 0x85, }
{ 0x63, 0xF7, 0xA6, }
{ 0x63, 0xF8, 0x47, }
{ 0x63, 0xF9, 0x68, }
{ 0x64, 0xCC, 0x31, }
{ 0x64, 0xCD, 0x10, }
{ 0x64, 0xD2, 0xED, }
{ 0x64, 0xD3, 0xCC, }
{ 0x64, 0xD6, 0x68, }
{ 0x64, 0xD7, 0x47, }
{ 0x64, 0xD8, 0xA6, }
{ 0x64, 0xD9, 0x85, }
{ 0x65, 0xAC, 0x10, }
{ 0x65, 0xAD, 0x31, }
{ 0x65, 0xB2, 0xCC, }
{ 0x65, 0xB3, 0xED, }
{ 0x65, 0xB6, 0x47, }
{ 0x65, 0xB7, 0x68, }
{ 0x65, 0xB8, 0x85, }
{ 0x65, 0xB9, 0xA6, }
{ 0x66, 0x8D, 0x31, }
{ 0x66, 0x8E, 0x10, }
{ 0x66, 0x91, 0xA6, }
{ 0x66, 0x92, 0x85, }
{ 0x66, 0x93, 0x68, }
{ 0x66, 0x94, 0x47, }
{ 0x66, 0x97, 0xED, }
{ 0x66, 0x98, 0xCC, }
{ 0x67, 0x6D, 0x10, }
{ 0x67, 0x6E, 0x31, }
{ 0x67, 0x71, 0x85, }
{ 0x67, 0x72, 0xA6, }
{ 0x67, 0x73, 0x47, }
{ 0x67, 0x74, 0x68, }
{ 0x67, 0x77, 0xCC, }
{ 0x67, 0x78, 0xED, }
{ 0x68, 0x4F, 0x31, }
{ 0x68, 0x50, 0x10, }
{ 0x68, 0x51, 0x68, }
{ 0x68, 0x52, 0x47, }
{ 0x68, 0x53, 0xA6, }
{ 0x68, 0x54, 0x85, }
{ 0x68, 0x55, 0xED, }
{ 0x68, 0x56, 0xCC, }
{ 0x69, 0x2F, 0x10, }
{ 0x69, 0x30, 0x31, }
{ 0x69, 0x31, 0x47, }
{ 0x69, 0x32, 0x68, }
{ 0x69, 0x33, 0x85, }
{ 0x69, 0x34, 0xA6, }
{ 0x69, 0x35, 0xCC, }
{ 0x69, 0x36, 0xED, }

Related

LED light up with c++

I tried to light a LED, which is connected with usb to the pc, with c++ and without using arduino. But my program doesn't want to light up my led. In the bytes_to_send array you can find the combination to that should light up the LEDs.
Anybody has any idea what should I modify?
int main()
{
HANDLE serialHandle;
serialHandle = CreateFile(L"COM4",GENERIC_READ | GENERIC_WRITE,0,0,OPEN_EXISTING,FILE_FLAG_OVERLAPPED,NULL);
if (serialHandle == INVALID_HANDLE_VALUE) {
printf("The Comport is closed or taken by another hardware/software!\n\r");
}
DCB serialParams = { 0 };
serialParams.DCBlength = sizeof(serialParams);
GetCommState(serialHandle, &serialParams);
serialParams.BaudRate = 9600;
serialParams.ByteSize = 8;
serialParams.StopBits = ONESTOPBIT;
serialParams.Parity = NOPARITY;
SetCommState(serialHandle, &serialParams);
COMMTIMEOUTS timeout = { 0 };
timeout.ReadIntervalTimeout = 50;
timeout.ReadTotalTimeoutConstant = 50;
timeout.ReadTotalTimeoutMultiplier = 50;
timeout.WriteTotalTimeoutConstant = 50;
timeout.WriteTotalTimeoutMultiplier = 10;
SetCommTimeouts(serialHandle, &timeout);
DWORD bytes_written, total_bytes_written = 0;
char bytes_to_send[7];
bytes_to_send[0] = 0x02, 0x03, 0x01;
bytes_to_send[1] = 0x12, 0x13, 0x11;
bytes_to_send[2] = 0x22, 0x23, 0x21;
bytes_to_send[3] = 0x32, 0x33, 0x31;
bytes_to_send[4] = 0x42, 0x43, 0x41;
bytes_to_send[5] = 0x52, 0x53, 0x51;
bytes_to_send[6] = 0x62, 0x63, 0x61;
WriteFile(serialHandle, bytes_to_send, 5, &bytes_written, NULL);
CloseHandle(serialHandle);
std::cout << "";
}

C++ heap corruption when delete is called on char array

hello I cannot understand why this is leading to when I delete this char buffer that the program is returning heap corruption. I made sure I am calling delete correctly for the correct type. I can only think that maybe ReadProcessMemory is causing problem. Furthermore, I am not sure though why this is happening .
#include "includes.h"
HANDLE pHandle;
//F2 ?? 0F 38 F1 ??
// { 0xF2, 0x48, 0x49, 0x0F, 0x38, 0xF1, 0x1C, 0xC2 }
struct crc32Values {
byte first;
byte skip;
byte skip2;
byte third1;
byte third2;
byte third3;
byte lastskip;
byte lastskip2;
};
HANDLE Cr32Scanner::LaunchSuspendedProcess(char* cmd, PHANDLE ptr_thread) // cleaned up a bit, but no RAII
{
if (ptr_thread == nullptr) return nullptr;
PROCESS_INFORMATION pi;
STARTUPINFOA si{}; // initialize with zeroes.
si.cb = sizeof(STARTUPINFOA);
if (!CreateProcessA(nullptr, cmd, nullptr, nullptr, false, CREATE_SUSPENDED,
nullptr, nullptr, std::addressof(si), std::addressof(pi)))
{
std::cerr << "CreateProcess failed, " << GetLastError() << '\n';
*ptr_thread = nullptr;
return nullptr;
}
*ptr_thread = pi.hThread;
return pi.hProcess;
}
void PrintAddress(unsigned char* value)
{
std::cout << std::hex << value << std::dec;
}
void Cr32Scanner::EnableDebugPriv()
{
HANDLE hToken;
LUID luid;
TOKEN_PRIVILEGES tkp;
OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken);
LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid);
tkp.PrivilegeCount = 1;
tkp.Privileges[0].Luid = luid;
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
AdjustTokenPrivileges(hToken, false, &tkp, sizeof(tkp), NULL, NULL);
CloseHandle(hToken);
}
void Cr32Scanner::GetVirtuInfo(HANDLE hprocess)
{
MEMORY_BASIC_INFORMATION mbi;
unsigned char* addr = 0;
while (VirtualQueryEx(hprocess, addr, &mbi, sizeof(mbi)))
{
if (mbi.State == MEM_COMMIT && mbi.Protect != PAGE_NOACCESS && mbi.Protect != PAGE_GUARD)
{
//std::cout << "base : 0x" << std::hex << mbi.BaseAddress << " end : 0x" << std::hex << (uintptr_t)mbi.BaseAddress + mbi.RegionSize << "\n";
this->InsertNodeAtLastPosition(&this->s_vmap, (uintptr_t)mbi.BaseAddress, (uintptr_t)mbi.BaseAddress + mbi.RegionSize, mbi.RegionSize);
}
addr += mbi.RegionSize;
}
//this->printList(this->s_vmap);
}
//F2 ?? 0F38F1 ?? ??
//F2 48 0F38F1 1C C2
//F2 49 0F38F1 04 C8
//F2 49 0F38F1 0C C0
//F2 48 0F38F1 3C C6
//F2 48 0F38F1 34 C7
//F2 48 0F38F1 3C C3
//F2 48 0F38F1 1C C7
bool found = false;
int main()
{
std::shared_ptr <Cr32Scanner> p_cr32scanner(new Cr32Scanner());
MEMORY_BASIC_INFORMATION MemInfo;
crc32Values s_crc32values = { 0xF2, 0x48, 0x49, 0x0F, 0x38, 0xF1, 0x1C, 0xC2 };
bool Is64Bit = false;
// set current process with admin token
p_cr32scanner->EnableDebugPriv();
char cmd[] = "C:\\Users\\Scd\\Desktop\\Testremmy_patched.exe"; // #notepad.exe"; // note: non-const (writeable array)
HANDLE thread = nullptr;
unsigned char* addr = 0;
std::cout << "Creating Process for " << cmd << std::endl;
HANDLE hprocess = p_cr32scanner->LaunchSuspendedProcess(cmd, std::addressof(thread));
p_cr32scanner->GetVirtuInfo(hprocess);
if (hprocess)
{
//GET NEXT blocks
VirtualAddressMap::vmap *currentNode = p_cr32scanner->s_vmap;
while(currentNode != nullptr){
long long StartAddress = currentNode->StartAddress;
long long EndAddress = currentNode->EndAddress;
size_t MemBlockSize = currentNode->RegionSize;
// CHECK BLOCK SIZES
std::cout << "Start Addr: " << std::hex << currentNode->StartAddress << " EndAddress " << std::hex << currentNode->EndAddress << " BlockSize " << currentNode->RegionSize << std::endl;
char* Buffer = new char[MemBlockSize + 1];
memset(&Buffer[0], 0, MemBlockSize + 1);
if (ReadProcessMemory(hprocess, (LPCVOID)(StartAddress), &Buffer, MemBlockSize, nullptr))
{
printf("[-] Error Occured - Failed to Read Memory. At Address -- 0x%llx 0x%08X \n", StartAddress, GetLastError());
break;
}
for (unsigned int i = 0; i < MemBlockSize; i++) {
if (Buffer[i] == s_crc32values.first) {
if (Buffer[i + 1] == s_crc32values.skip || Buffer[i + 1] == s_crc32values.skip2) {
if (Buffer[i + 2] == s_crc32values.third1) {
if (Buffer[i + 3] == s_crc32values.third2) {
if (Buffer[i + 4] == s_crc32values.third3) {
printf("CRC32 Found! at 0x%llx\n", StartAddress + i);
//found = true;
//break;
}
}
}
}
}
}
currentNode = currentNode->Next;
// crash here.
// delete[] Buffer;
}
std::cout << "press enter to resume process... " && std::cin.get();
ResumeThread(thread);
CloseHandle(thread);
CloseHandle(hprocess);
}
}
if (ReadProcessMemory(hprocess, (LPCVOID)(StartAddress), &Buffer, MemBlockSize, nullptr))
The third parameter to ReadProcessMemory is supposed to be a pointer to the buffer, not a pointer to the address of the buffer.

string size after converting const unsigned char[] to std::string

I tried to convert unsigned char array to an std::string of size 16.
But I don`t know why result string size is different.
I want to know the reason.
#include <iostream>
using namespace std;
const unsigned char t[16] = { 0x1E, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 ,0x08 ,0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15 };
const unsigned char t2[16] = { 0x1E, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 ,0x08 ,0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15 };
const unsigned char t3[16] = { 0x44, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47 ,0x68 ,0x69, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65 };
int main() {
string a, a2, a3;
a = static_cast<std::string>(reinterpret_cast<const char*>(t));
a2.assign(reinterpret_cast<const char*>(t2), 16);
a3.assign(reinterpret_cast<const char*>(t3));
cout << "size : " << a.size() << endl;
for (int i = 0; i < a.size(); i++)
printf("0x%02X ", a.c_str()[i]);
cout << endl << endl;
cout << "size2 : " << a2.size() << endl;
for (int i = 0; i < a2.size(); i++)
printf("0x%02X ", a2.c_str()[i]);
cout << endl << endl;
cout << "size3 : " << a3.size() << endl;
for (int i = 0; i < a3.size(); i++)
printf("0x%02X ", a3.c_str()[i]);
cout << endl << endl;
return 0;
}
result
size : 56
0x1E 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x10 0x11
0x12 0x13 0x14 0x15 0x1E 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09
0x10 0x11 0x12 0x13 0x14 0x15 0x44 0x41 0x42 0x43 0x44 0x45 0x46 0x47
0x68 0x69 0x60 0x61 0x62 0x63 0x64 0x65 0x5F 0x41 0x72 0x67 0x4C 0x69
0x73 0x74
size2 : 16
0x1E 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x10 0x11
0x12 0x13 0x14 0x15
size3 : 24
0x44 0x41 0x42 0x43 0x44 0x45 0x46 0x47 0x68 0x69 0x60 0x61
0x62 0x63 0x64 0x65 0x5F 0x41 0x72 0x67 0x4C 0x69 0x73 0x74
case 1: input is not explicitly null-terminated, and likely those global arrays are placed in memory sequentially, so you get at least 48 bytes without zeros, finally it finds some zero 8 bytes ahead, so total is 56.
case 2: here you give it explicit length, and that's the correct way to do things in case of null terminator absence.
case 3: similar to case 1, but just starts from array 3, and takes same extra 8 bytes until null terminator found somewhere.
Solutions: either add null terminators (zero byte) or use variant with explicit length specification.

Winsock Bluetooth subsequent calls to send function fails with WSAECONNABORTED

I am trying to create simple windows bluetooth client application. However after successfull connect the send() function is sending data only for a short duration. The subsequent calls to send() function fail with code: 10053 (WSAECONNABORTED).
From docs:
Software caused connection abort. An established connection was aborted by the software in your host computer, possibly due to a data transmission time-out or protocol error.
If I understand it correctly the error is occuring on Windows (client) side and not on the server side?
What could be causing it?
Also is it possible to somehow reconnect this socket?
The code (simplified, missing error checks):
#include <winsock2.h>
#include <ws2bth.h>
#include <iostream>
// {B62C4E8D-62CC-404b-BBBF-BF3E3BBB1374} ]taken from Microsoft example
DEFINE_GUID(gGuidServiceClass, 0xb62c4e8d, 0x62cc, 0x404b, 0xbb, 0xbf, 0xbf, 0x3e, 0x3b, 0xbb, 0x13, 0x74);
unsigned char dummyData [10] =
{
0x01, 0x02, 0x03, 0x04, 0x05,
0x01, 0x02, 0x03, 0x04, 0x05
};
int main(void)
{
WSAData wsaData = {0};
SOCKADDR_BTH btAddr = {0};
uint32_t flags = 0;
WSAStartup(MAKEWORD(2, 2), &wsaData);
btAddr.addressFamily = AF_BTH;
btAddr.serviceClassId = gGuidServiceClass;
btAddr.port = 0;
btAddr.btAddr = // hardcoded address here
SOCKET s = socket(AF_BTH, SOCK_STREAM, BTHPROTO_RFCOMM);
if (SOCKET_ERROR == connect(s, (struct sockaddr *) &btAddr, sizeof(SOCKADDR_BTH)))
{
std::cout << "socket connect fail: " << WSAGetLastError() << std::endl;
return -1;
}
int32_t bytes = send(s, reinterpret_cast<char *>(dummyData), 10, 0);
if (bytes == 10)
{
std::cout << "first send success\n";
}
// success
// do some processing
// repeat
bytes = send(s, reinterpret_cast<char *>(dummyData), 10, 0);
if (bytes < 0)
{
// always fail with 10053
std::cout << "Error: " << WSAGetLastError() << std::endl;
}
closesocket(s);
WSACleanup();
return 0;
}

Can't connect or publish to MQTT broker with Arduino and SIM900

I have written a simple sketch to send a connect and publish packet to a cloudMQTT server. I get no errors back from the SIM900 but nothing shows up on the cloudMQTT dashboard.
#include <SoftwareSerial.h>
SoftwareSerial SoftSerial( 9, 10 );
// These varaibles are passed to functionality that generates the connect and publish packets. This code was taken from a sketch written by Ravi Pujar
unsigned int Counter = 0;
unsigned long datalength, CheckSum, RLength;
unsigned short topiclength;
unsigned char topic[30];
char str[250];
unsigned char encodedByte;
int X;
unsigned short MQTTProtocolNameLength;
unsigned short MQTTClientIDLength;
unsigned short MQTTUsernameLength;
unsigned short MQTTPasswordLength;
const char MQTTHost[30] = "hairdresser.cloudmqtt.com";
const char MQTTPort[10] = "18958";
const char MQTTClientID[20] = "ABCDEF";
const char MQTTTopic[30] = "valetron";
const char MQTTProtocolName[10] = "MQIsdp";
const char MQTTLVL = 0x03;
const char MQTTFlags = 0xC2;
const unsigned int MQTTKeepAlive = 60;
const char MQTTUsername[30] = "uroxeeil";
const char MQTTPassword[35] = "ifG3xIxaf5gT";
const char MQTTQOS = 0x00;
const char MQTTPacketID = 0x0001;
unsigned char buffer[ 64 ];
int counter = 0;
void setup()
{
// Set the babud rate of both the software serial and hardware serial
Serial.begin( 19200 );
SoftSerial.begin( 19200 );
delay(2000);
// This section of code sends AT commands to initialize the SIM900
//-------------- AT INITIALIZATION - This is working fine--------------//
SoftSerial.write( "\r\nAT\r\n" );
delay(3000);
while ( SoftSerial.available() > 0 )
{
buffer[ counter++ ] = SoftSerial.read();
if( counter == 64 ) break;
}
Serial.write( buffer, counter );
for( int i = 0; i < counter; i++ )
{
buffer[ i ] = NULL;
}
counter = 0;
delay(2000);
//-----
SoftSerial.write( "\r\nAT+CIPSHUT\r\n" );
delay(3000);
while ( SoftSerial.available() > 0 )
{
buffer[ counter++ ] = SoftSerial.read();
if( counter == 64 ) break;
}
Serial.write( buffer, counter );
for( int i = 0; i < counter; i++ )
{
buffer[ i ] = NULL;
}
counter = 0;
delay(2000);
//-----
SoftSerial.write( "\r\nAT+CIPMUX=0\r\n" );
delay(3000);
while ( SoftSerial.available() > 0 )
{
buffer[ counter++ ] = SoftSerial.read();
if( counter == 64 ) break;
}
Serial.write( buffer, counter );
for( int i = 0; i < counter; i++ )
{
buffer[ i ] = NULL;
}
counter = 0;
delay(2000);
//-----
SoftSerial.write( "\r\nAT+CGATT=1\r\n" );
delay(3000);
while ( SoftSerial.available() > 0 )
{
buffer[ counter++ ] = SoftSerial.read();
if( counter == 64 ) break;
}
Serial.write( buffer, counter );
for( int i = 0; i < counter; i++ )
{
buffer[ i ] = NULL;
}
counter = 0;
delay(2000);
//-----
SoftSerial.write( "\r\nAT+CSTT=\"myMTN\", \"\", \"\"\r\n" );
delay(3000);
while ( SoftSerial.available() > 0 )
{
buffer[ counter++ ] = SoftSerial.read();
if( counter == 64 ) break;
}
Serial.write( buffer, counter );
for( int i = 0; i < counter; i++ )
{
buffer[ i ] = NULL;
}
counter = 0;
delay(2000);
//-----
SoftSerial.write( "\r\nAT+CIICR\r\n" );
delay(3000);
while ( SoftSerial.available() > 0 )
{
buffer[ counter++ ] = SoftSerial.read();
if( counter == 64 ) break;
}
Serial.write( buffer, counter );
for( int i = 0; i < counter; i++ )
{
buffer[ i ] = NULL;
}
counter = 0;
delay(2000);
//-----
SoftSerial.write( "\r\nAT+CIFSR\r\n" );
delay(3000);
while ( SoftSerial.available() > 0 )
{
buffer[ counter++ ] = SoftSerial.read();
if( counter == 64 ) break;
}
Serial.write( buffer, counter );
for( int i = 0; i < counter; i++ )
{
buffer[ i ] = NULL;
}
counter = 0;
delay(2000);
//-----
SoftSerial.write( "\r\nAT+CIPSTART=\"TCP\", \"hairdresser.cloudmqtt.com\", \"18958\"\r\n" );
delay(10000);
while ( SoftSerial.available() > 0 )
{
buffer[ counter++ ] = SoftSerial.read();
if( counter == 64 ) break;
}
Serial.write( buffer, counter );
for( int i = 0; i < counter; i++ )
{
buffer[ i ] = NULL;
}
counter = 0;
delay(2000);
//-------------- END OF AT INITIALIZATION --------------//
//This is where the issue lies
// Send the connect packet. This code was written by Ravi Pujar
SoftSerial.write( "\r\nAT+CIPSEND\r\n" );
delay(3000);
SoftSerial.write(0x10);
MQTTProtocolNameLength = strlen(MQTTProtocolName);
MQTTClientIDLength = strlen(MQTTClientID);
MQTTUsernameLength = strlen(MQTTUsername);
MQTTPasswordLength = strlen(MQTTPassword);
datalength = MQTTProtocolNameLength + 2 + 4 + MQTTClientIDLength + 2 + MQTTUsernameLength + 2 + MQTTPasswordLength + 2;
X = datalength;
do {
encodedByte = X % 128;
X = X / 128;
if (X > 0) {
encodedByte |= 128;
}
SoftSerial.write(encodedByte);
}
while (X > 0);
SoftSerial.write(MQTTProtocolNameLength >> 8);
SoftSerial.write(MQTTProtocolNameLength & 0xFF);
SoftSerial.print(MQTTProtocolName);
SoftSerial.write(MQTTLVL); // LVL
SoftSerial.write(MQTTFlags); // Flags
SoftSerial.write(MQTTKeepAlive >> 8);
SoftSerial.write(MQTTKeepAlive & 0xFF);
SoftSerial.write(MQTTClientIDLength >> 8);
SoftSerial.write(MQTTClientIDLength & 0xFF);
SoftSerial.print(MQTTClientID);
SoftSerial.write(MQTTUsernameLength >> 8);
SoftSerial.write(MQTTUsernameLength & 0xFF);
SoftSerial.print(MQTTUsername);
SoftSerial.write(MQTTPasswordLength >> 8);
SoftSerial.write(MQTTPasswordLength & 0xFF);
SoftSerial.print(MQTTPassword);
SoftSerial.write(0x1A);
delay( 2000 );
// Send the publish packet. This code was written by Ravi Pujar
SoftSerial.print("\r\nAT+CIPSEND\r\n");
delay(3000);
memset(str, 0, 250);
topiclength = sprintf((char * ) topic, MQTTTopic);
datalength = sprintf((char * ) str, "%s%u", topic, Counter);
delay(1000);
Serial.write(0x30);
X = datalength + 2;
do {
encodedByte = X % 128;
X = X / 128;
if (X > 0) {
encodedByte |= 128;
}
SoftSerial.write(encodedByte);
}
while (X > 0);
SoftSerial.write(topiclength >> 8);
SoftSerial.write(topiclength & 0xFF);
SoftSerial.print(str);
SoftSerial.write(0x1A);
}
void loop()
{
// Display any response that has been sent after the first CIPSEND
while ( SoftSerial.available() > 0 )
{
buffer[ counter++ ] = SoftSerial.read();
if( counter == 64 ) break;
}
Serial.write( buffer, counter );
for( int i = 0; i < counter; i++ )
{
buffer[ i ] = NULL;
}
counter = 0;
}
This is the Serial output:
But nothing shows on the cloudMQTT server besides the IP of my device after the tcp connection is established.
So it was not working when trying to connect to the cloudMQTT server, but when I connected to my MQTT server or the test MQTT server, it worked. There must be an issue dealing with the protocol that the cloud mqttServer uses (MQIsdp) as apposed to the standard MQTT protocol that a normal MQTT server utilizes. I made a change to the connect packet so that it specified the MQTT protocol and pointed the TCP connection to the test server ( test.mosquitto.org ) and I can now Connect and Publish successfully.
For anyone who is just starting out with trying to interface an Arduino with a module like a SIM900 ( GPRS/GSM module ) to a MQTT server, I suggest you grasp a full understanding of standard AT Commands ( To establish a solid TCP connection to server ), how to compile the packets that will be sent through the GPRS module from the Arduino and lastly I suggest not using any code you have not written to achieve this. Learn how to establish the TCP connection with AT commands, then learn how to compile and send a connect packet by compiling the byte array yourself and sending it. Once you understand the packets and the communication between the client and the server, the MQTT world is your oyster.
You can use this code as a guideline but please try write as much of your own as possible:
#include <SoftwareSerial.h>
SoftwareSerial SoftSerial( 9, 10 );
// Go Look up the structure of MQTT packets and from there you will learn how to compile these
byte connectPacket[ 19 ] =
{
0x10, 0x11, 0x00, 0x04, 0x4D, 0x51, 0x54, 0x54, 0x04, 0x02, 0x00, 0x3C, 0x00, 0x05, 0x54, 0x32, 0x54, 0x49, 0x44
};
byte publishPacket[ 26 ] =
{
0x30, 0x18, 0x00, 0x0E, 0x54, 0x32, 0x54, 0x5F, 0x54, 0x6F, 0x70, 0x69, 0x63, 0x5F, 0x44, 0x65, 0x6D, 0x6F, 0x54, 0x65, 0x6D, 0x70, 0x3A, 0x20, 0x33, 0x30
};
unsigned char buffer[ 64 ];
int counter = 0;
// Simple function to send an AT command and see its response
void sendAtCommandWithResponse( char message[] )
{
SoftSerial.write( message );
delay(3000);
while ( SoftSerial.available() > 0 )
{
buffer[ counter++ ] = SoftSerial.read();
if( counter == 64 ) break;
}
Serial.write( buffer, counter );
for( int i = 0; i < counter; i++ )
{
buffer[ i ] = NULL;
}
counter = 0;
}
void setup()
{
Serial.begin( 19200 );
SoftSerial.begin( 19200 );
delay(10000);
// -- Configure the SIM900 and establish the TCP connection to the server
sendAtCommandWithResponse( "\r\nAT\r\n" );
delay(2000);
//-----
sendAtCommandWithResponse( "\r\nAT+CIPSHUT\r\n" );
delay(2000);
//-----
sendAtCommandWithResponse( "\r\nAT+CIPMUX=0\r\n" );
delay(2000);
//-----
sendAtCommandWithResponse( "\r\nAT+CGATT=1\r\n" );
delay(2000);
//-----
sendAtCommandWithResponse( "\r\nAT+CSTT=\"myMTN\", \"\", \"\"\r\n" );
delay(2000);
//-----
sendAtCommandWithResponse( "\r\nAT+CIICR\r\n" );
delay(2000);
//-----
sendAtCommandWithResponse( "\r\nAT+CIFSR\r\n" );
delay(2000);
//-----
SoftSerial.write( "\r\nAT+CIPSTART=\"TCP\", \"test.mosquitto.org\", \"1883\"\r\n" );
delay(10000);
//-----
while ( SoftSerial.available() > 0 )
{
buffer[ counter++ ] = SoftSerial.read();
if( counter == 64 ) break;
}
Serial.write( buffer, counter );
for( int i = 0; i < counter; i++ )
{
buffer[ i ] = NULL;
}
counter = 0;
delay(2000);
//-----
// -- Send the connect packet
sendAtCommandWithResponse( "\r\nAT+CIPSEND\r\n" );
delay(3000);
SoftSerial.write( connectPacket, sizeof( connectPacket ) );
// This tells the SIM900 to send the packet
SoftSerial.write(0x1A);
delay(3000);
// -- Send the publish packet
sendAtCommandWithResponse( "\r\nAT+CIPSEND\r\n" );
delay(3000);
SoftSerial.write( publishPacket, sizeof( publishPacket ) );
// This tells the SIM900 to send the packet
SoftSerial.write(0x1A);
}
void loop()
{
while ( SoftSerial.available() > 0 )
{
buffer[ counter++ ] = SoftSerial.read();
if( counter == 64 ) break;
}
Serial.write( buffer, counter );
for( int i = 0; i < counter; i++ )
{
buffer[ i ] = NULL;
}
counter = 0;
}