Skip to content

Commit ae5c324

Browse files
authored
Support big endian system (xfangfang#52)
* PackageBuilder support big endian * Support MIPS big endian * Support building for more big endian architectures * Fix CI build error * Fix pppoe_softc_list * Fix UDP fragmentOffset * Fix for PCPP_IP_MORE_FRAGMENTS flag * Fix UDP checksum * Fix LCP magic number
1 parent 8265c1a commit ae5c324

File tree

10 files changed

+211
-64
lines changed

10 files changed

+211
-64
lines changed

.github/workflows/ci.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ jobs:
4848
cmake: "-DUSE_SYSTEM_PCAP=OFF -DZIG_COMPILE_OPTION='-mcpu=arm1176jzf_s'", name: "(pi_zero_w)" }
4949
- { target: mipsel-linux-musl, os: ubuntu-latest, strip: "llvm-strip", upx: "upx --lzma",
5050
cmake: "-DUSE_SYSTEM_PCAP=OFF -DZIG_COMPILE_OPTION='-msoft-float'" }
51+
- { target: mips-linux-musl, os: ubuntu-latest, strip: "llvm-strip", upx: "upx --lzma",
52+
cmake: "-DUSE_SYSTEM_PCAP=OFF -DZIG_COMPILE_OPTION='-msoft-float'" }
5153
steps:
5254
- uses: actions/checkout@v4
5355

CMakeLists.txt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,17 @@ else ()
9494
set_property(TARGET Pcap++ PROPERTY COMPILE_WARNING_AS_ERROR OFF)
9595
set_property(TARGET Common++ PROPERTY COMPILE_WARNING_AS_ERROR OFF)
9696
list(APPEND APP_LINK_LIB Pcap++)
97+
set(ZIG_BE "mips" "mips64" "armeb" "powerpc64" "powerpc" "aarch64_be" "s390x")
98+
list(FIND ZIG_BE "${ZIG_TARGET_ARCH}" INDEX)
99+
if (${INDEX} GREATER -1)
100+
message(STATUS "Patching Layer.h to support big endian when cross-compiling")
101+
add_custom_target(PatchLayer
102+
WORKING_DIRECTORY ${PcapPlusPlus_SOURCE_DIR}
103+
COMMAND git checkout -- ${PcapPlusPlus_SOURCE_DIR}/Packet++/header/Layer.h
104+
COMMAND git apply --stat --apply ${CMAKE_SOURCE_DIR}/endian.patch
105+
)
106+
add_dependencies(Packet++ PatchLayer)
107+
endif ()
97108
endif ()
98109

99110
add_library(${PROJECT_NAME}_static STATIC src/exploit.cpp src/packet.cpp)

endian.patch

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
diff --git a/Packet++/header/Layer.h b/Packet++/header/Layer.h
2+
index afa1d3fa..438ab99c 100644
3+
--- a/Packet++/header/Layer.h
4+
+++ b/Packet++/header/Layer.h
5+
@@ -4,6 +4,7 @@
6+
#include <stdint.h>
7+
#include <stdio.h>
8+
#include "ProtocolType.h"
9+
+#include "EndianPortable.h"
10+
#include <string>
11+
12+
/// @file

include/exploit.h

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,12 @@
1212
#define RETURN_FAIL 1
1313
#define RETURN_SUCCESS 0
1414

15-
#ifdef DEBUG
16-
#define hexdump(p) PacketBuilder::hexPrint(p)
17-
#define hexdump_verbose(p) (void) p
18-
19-
#else
20-
#define hexdump(p) (void) p
21-
#define hexdump_verbose(p) (void) p
22-
#endif
15+
#define hexdump(p) if(PacketBuilder::debug) PacketBuilder::hexPrint(p)
2316

2417
class PacketBuilder {
2518
public:
19+
static void hexPrint(const uint8_t* data, size_t len);
20+
2621
static void hexPrint(const pcpp::Packet &packet);
2722

2823
static pcpp::Packet lcpEchoReply(const pcpp::MacAddress &source_mac, const pcpp::MacAddress &target_mac,
@@ -64,6 +59,8 @@ class PacketBuilder {
6459
static pcpp::PPPoESessionLayer *getPPPoESessionLayer(const pcpp::Packet &packet, uint16_t pppType);
6560

6661
static pcpp::PPPoEDiscoveryLayer *getPPPoEDiscoveryLayer(const pcpp::Packet &packet, uint8_t type);
62+
63+
static inline bool debug{};
6764
};
6865

6966
class Exploit {

src/exploit.cpp

Lines changed: 34 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -71,10 +71,20 @@ struct Cookie {
7171
#define CORRUPT_NUM 0x1
7272
#endif
7373

74-
// todo: Support big endian system
75-
#define V64(list, index, data) (*(uint64_t *) &(list)[index]) = data
76-
#define V32(list, index, data) (*(uint32_t *) &(list)[index]) = data
77-
#define V16(list, index, data) (*(uint16_t *) &(list)[index]) = data
74+
#ifndef htole64
75+
#define htole64
76+
#endif
77+
#ifndef htole32
78+
#define htole32
79+
#endif
80+
#ifndef htole16
81+
#define htole16
82+
#endif
83+
84+
#define V64BE(list, index, data) (*(uint64_t *) &(list)[index]) = htobe64(data)
85+
#define V64(list, index, data) (*(uint64_t *) &(list)[index]) = htole64(data)
86+
#define V32(list, index, data) (*(uint32_t *) &(list)[index]) = htole32(data)
87+
#define V16(list, index, data) (*(uint16_t *) &(list)[index]) = htole16(data)
7888
#define V8(list, index, data) (*(uint8_t *) &(list)[index]) = data
7989

8090
#define CHECK_RET(value) { int ret = (value); if(ret != RETURN_SUCCESS) return ret;}
@@ -198,6 +208,7 @@ void Exploit::updateSourceMac(uint64_t value) {
198208
};
199209
Converter planted{};
200210
planted.u64 = value & 0xffffffffffff;
211+
planted.u64 = htole64(planted.u64);
201212
this->source_mac = pcpp::MacAddress(planted.u8);
202213
std::cout << "[+] Source MAC: " << this->source_mac.toString() << std::endl;
203214
}
@@ -361,6 +372,7 @@ int Exploit::ppp_negotiation(const std::function<std::vector<uint8_t>(Exploit *)
361372
}
362373

363374
memcpy(&pppoe_softc, host_uniq, sizeof(pppoe_softc));
375+
pppoe_softc = htole64(pppoe_softc);
364376
std::cout << "[+] pppoe_softc: 0x" << std::hex << pppoe_softc << std::endl;
365377

366378
auto *ethLayer = pkt.packet.getLayerOfType<pcpp::EthLayer>();
@@ -514,7 +526,7 @@ std::vector<uint8_t> Exploit::build_fake_lle(Exploit *self) {
514526
V64(fake_lle, 0x70, 0x7fffffffffffffff); // ln_ntick
515527
V32(fake_lle, 0x78, 0); // lle_refcnt
516528
V32(fake_lle, 0x7C, 0); // pad
517-
V64(fake_lle, 0x80, htobe64(0x414141414141)); // ll_addr
529+
V64BE(fake_lle, 0x80, 0x414141414141); // ll_addr
518530

519531
// lle_timer
520532
V64(fake_lle, 0x88, 0); // sle
@@ -533,8 +545,8 @@ std::vector<uint8_t> Exploit::build_fake_lle(Exploit *self) {
533545
V16(fake_lle, 0xC2, 0); // sin6_port
534546
V32(fake_lle, 0xC4, 0); // sin6_flowinfo
535547
// sin6_addr
536-
V64(fake_lle, 0xC8, htobe64(0xfe80000100000000));
537-
V64(fake_lle, 0xD0, htobe64(0x4141414141414141));
548+
V64BE(fake_lle, 0xC8, 0xfe80000100000000);
549+
V64BE(fake_lle, 0xD0, 0x4141414141414141);
538550
V32(fake_lle, 0xD8, 0); // sin6_scope_id
539551

540552
// pad
@@ -769,7 +781,7 @@ int Exploit::stage1() {
769781
auto &&echoReply = PacketBuilder::lcpEchoReply(etherLayer->getDestMac(), etherLayer->getSourceMac(),
770782
pppLayer->getPPPoEHeader()->sessionId,
771783
pppLayer->getLayerPayload()[1], // id
772-
*(uint32_t * ) & pppLayer->getLayerPayload()[4]); // magic number
784+
htole32(*(uint32_t * ) & pppLayer->getLayerPayload()[4])); // magic number
773785
device->sendPacket(&echoReply);
774786
}, nullptr);
775787

@@ -904,7 +916,7 @@ int Exploit::stage2() {
904916
if (option[0] != 1) return false; // type 1 is ICMPv6NDOptSrcLLAddr
905917
if (option[1] > 1) {
906918
auto *self = (Exploit *) cookie;
907-
self->pppoe_softc_list = *(uint64_t * )(option + 3);
919+
self->pppoe_softc_list = htole64(*(uint64_t * )(option + 3));
908920
return true; // length > 1
909921
}
910922
return false;
@@ -981,7 +993,7 @@ int Exploit::stage4() {
981993
ipLayer.getIPv4Header()->timeToLive = 0x40;
982994
ipLayer.getIPv4Header()->ipId = htobe16(1);
983995
ipLayer.getIPv4Header()->protocol = pcpp::IPProtocolTypes::PACKETPP_IPPROTO_UDP;
984-
ipLayer.getIPv4Header()->fragmentOffset = htobe16(offset / 8 + (offset != 0)) | PCPP_IP_MORE_FRAGMENTS;
996+
ipLayer.getIPv4Header()->fragmentOffset = htobe16(offset / 8 + (offset != 0)) | htobe16(0x2000);
985997
ipLayer.getFragmentOffset();
986998
packet.addLayer(&ipLayer);
987999

@@ -996,7 +1008,7 @@ int Exploit::stage4() {
9961008

9971009
// last fragment
9981010
if (offset + payloadSize >= this->stage2_bin.size()) {
999-
ipLayer.getIPv4Header()->fragmentOffset = htobe16(offset / 8 + (offset != 0)) & 0xFF1F;
1011+
ipLayer.getIPv4Header()->fragmentOffset = htobe16(offset / 8 + (offset != 0)) & htobe16(0x1FFF);
10001012
payloadSize = this->stage2_bin.size() - offset;
10011013
}
10021014

@@ -1014,10 +1026,10 @@ int Exploit::stage4() {
10141026

10151027
// Calculate checksum
10161028
std::vector<uint8_t> temp(udpLayer.getHeaderLen());
1017-
V16(temp, 0, udpHeader->portSrc);
1018-
V16(temp, 2, udpHeader->portDst);
1019-
V16(temp, 4, udpHeader->length);
1020-
V16(temp, 6, 0);
1029+
(*(uint16_t *) &(temp)[0]) = udpHeader->portSrc;
1030+
(*(uint16_t *) &(temp)[2]) = udpHeader->portDst;
1031+
(*(uint16_t *) &(temp)[4]) = udpHeader->length;
1032+
(*(uint16_t *) &(temp)[6]) = 0;
10211033
temp.insert(temp.end(), this->stage2_bin.begin(), this->stage2_bin.end());
10221034
uint16_t checksumRes = pcpp::computePseudoHdrChecksum(temp.data(),
10231035
temp.size(),
@@ -1088,34 +1100,23 @@ int Exploit::run() {
10881100
return RETURN_SUCCESS;
10891101
}
10901102

1091-
template<auto M>
1103+
template<auto M, auto N>
10921104
struct Tunnel;
10931105

1094-
template<class T, class U, T U::*M>
1095-
struct Tunnel<M> {
1106+
template<class T, class V, class Q, class U, T U::*M, Q V::*N>
1107+
struct Tunnel<M, N> {
10961108
friend T &stopThread(U &u) {
10971109
return u.*M;
10981110
}
1099-
};
1100-
1101-
template
1102-
struct Tunnel<&pcpp::PcapLiveDevice::m_StopThread>;
1103-
1104-
std::atomic<bool> &stopThread(pcpp::PcapLiveDevice &);
1105-
1106-
template<auto M>
1107-
struct Tunnel2;
1108-
1109-
template<class T, class U, T U::*M>
1110-
struct Tunnel2<M> {
1111-
friend T &pcapHandle(U &u) {
1112-
return u.*M;
1111+
friend Q &pcapHandle(V &u) {
1112+
return u.*N;
11131113
}
11141114
};
11151115

11161116
template
1117-
struct Tunnel2<&pcpp::IPcapDevice::m_PcapDescriptor>;
1117+
struct Tunnel<&pcpp::PcapLiveDevice::m_StopThread, &pcpp::IPcapDevice::m_PcapDescriptor>;
11181118

1119+
std::atomic<bool> &stopThread(pcpp::PcapLiveDevice &);
11191120
pcap_t *&pcapHandle(pcpp::IPcapDevice &);
11201121

11211122
void Exploit::stop() {

src/packet.cpp

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,6 @@ class MyPPPoETagBuilder : public pcpp::PPPoEDiscoveryLayer::PPPoETagBuilder {
4747
}
4848
};
4949

50-
uint16_t force_htole16(uint16_t host_16bits) {
51-
return ((host_16bits >> 8) & 0xff) | ((host_16bits << 8) & 0xff00);
52-
}
53-
5450
uint16_t p16be(uint64_t val) {
5551
return htobe16(static_cast<uint16_t>(val & 0xffff));
5652
}
@@ -63,7 +59,7 @@ static pcpp::PayloadLayer *buildPPPLayer(pcpp::PPPoELayer *last, uint8_t code, u
6359
(*(uint16_t * ) & ppp_data[2]) = p16be(4 + data_len);
6460
if (data_len > 0) memcpy(&ppp_data[4], data, data_len);
6561
auto *pppLayer = new pcpp::PayloadLayer(ppp_data, sizeof(ppp_data), false);
66-
last->getPPPoEHeader()->payloadLength = p16be(force_htole16(last->getPPPoEHeader()->payloadLength) +
62+
last->getPPPoEHeader()->payloadLength = p16be(p16be(last->getPPPoEHeader()->payloadLength) +
6763
sizeof(ppp_data) + sizeof(uint16_t));
6864
return pppLayer;
6965
}
@@ -75,7 +71,7 @@ static pcpp::PayloadLayer *buildPPPLayer(pcpp::PPPoELayer *last, uint8_t code, u
7571
ppp_data[1] = id;
7672
(*(uint16_t * ) & ppp_data[2]) = p16be(4 + data_len);
7773
auto *pppLayer = new pcpp::PayloadLayer(ppp_data, sizeof(ppp_data), false);
78-
last->getPPPoEHeader()->payloadLength = p16be(force_htole16(last->getPPPoEHeader()->payloadLength) +
74+
last->getPPPoEHeader()->payloadLength = p16be(p16be(last->getPPPoEHeader()->payloadLength) +
7975
sizeof(ppp_data) + sizeof(uint16_t));
8076
return pppLayer;
8177
}
@@ -86,30 +82,34 @@ static pcpp::PayloadLayer *buildPPPLCPOptionLayer(pcpp::PPPoELayer *last, const
8682
option_data[1] = data_len + 2; // len
8783
if (data_len > 0) memcpy(&option_data[2], data, data_len);
8884
auto *pppLayer = new pcpp::PayloadLayer(option_data, sizeof(option_data), false);
89-
last->getPPPoEHeader()->payloadLength = p16be(force_htole16(last->getPPPoEHeader()->payloadLength) +
85+
last->getPPPoEHeader()->payloadLength = p16be(p16be(last->getPPPoEHeader()->payloadLength) +
9086
sizeof(option_data));
9187
return pppLayer;
9288
}
9389

94-
void PacketBuilder::hexPrint(const pcpp::Packet &packet) {
95-
auto *rawData = packet.getRawPacket()->getRawData();
90+
void PacketBuilder::hexPrint(const uint8_t* data, size_t len) {
9691
std::stringstream ss;
9792
ss << std::hex;
98-
for (int i = 0; i < packet.getRawPacket()->getRawDataLen(); ++i) {
93+
for (int i = 0; i < len; ++i) {
9994
if (i % 16 == 0) {
10095
if (i != 0) ss << "\n";
10196
ss << std::setw(4) << std::setfill('0') << i << " ";
10297
}
103-
ss << std::setw(2) << std::setfill('0') << (int) rawData[i] << " ";
98+
ss << std::setw(2) << std::setfill('0') << (int) data[i] << " ";
10499
}
105100
std::cout << ss.str() << std::endl;
106101
}
107102

103+
void PacketBuilder::hexPrint(const pcpp::Packet &packet) {
104+
PacketBuilder::hexPrint(packet.getRawPacket()->getRawData(), packet.getRawPacket()->getRawDataLen());
105+
}
106+
108107
pcpp::Packet PacketBuilder::lcpEchoReply(const pcpp::MacAddress &source_mac, const pcpp::MacAddress &target_mac,
109108
uint16_t session, uint8_t id, uint32_t magic_number) {
110109
auto *ether = new pcpp::EthLayer(source_mac, target_mac, PCPP_ETHERTYPE_PPPOES);
111110
auto *pppoeLayer = new pcpp::PPPoESessionLayer(1, 1, session, PCPP_PPP_LCP);
112111

112+
magic_number = htole32(magic_number);
113113
auto *lcpEchoReply = buildPPPLayer(pppoeLayer, ECHO_REPLY, id, (uint8_t * ) & magic_number, sizeof(uint32_t));
114114

115115
pcpp::Packet packet;
@@ -190,7 +190,10 @@ pcpp::Packet PacketBuilder::ipcpRequest(const pcpp::MacAddress &source_mac, cons
190190
std::vector<uint8_t> data(6);
191191
data[0] = PPP_IPCP_Option_IP;
192192
data[1] = data.size();
193-
*(uint32_t * )(&data[2]) = pcpp::IPv4Address(SOURCE_IPV4).toInt();
193+
uint32_t ip = pcpp::IPv4Address(SOURCE_IPV4).toInt();
194+
for (int i = 0; i < 4; ++i) {
195+
data[i + 2] = (ip >> (i * 8)) & 0xFF;
196+
}
194197
pcpp::PayloadLayer *pppLayer = buildPPPLayer(pppoeLayer, CONF_REQ, IPCP_ID, data.data(), data.size());
195198

196199
pcpp::Packet packet;
@@ -209,7 +212,10 @@ PacketBuilder::ipcpNak(const pcpp::MacAddress &source_mac, const pcpp::MacAddres
209212
std::vector<uint8_t> data(6);
210213
data[0] = PPP_IPCP_Option_IP;
211214
data[1] = data.size();
212-
*(uint32_t * )(&data[2]) = pcpp::IPv4Address(TARGET_IPV4).toInt();
215+
uint32_t ip = pcpp::IPv4Address(TARGET_IPV4).toInt();
216+
for (int i = 0; i < 4; ++i) {
217+
data[i + 2] = (ip >> (i * 8)) & 0xFF;
218+
}
213219
pcpp::PayloadLayer *pppLayer = buildPPPLayer(pppoeLayer, CONF_NAK, id, data.data(), data.size());
214220

215221
pcpp::Packet packet;

tests/CMakeLists.txt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,9 @@ add_custom_target(${PROJECT_NAME}_pybind ALL
1919
DEPENDS ${PROJECT_NAME}_shared
2020
COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/pppwn.py
2121
--interface=${IFACE} --fw=${FW} --stage1=${STAGE1} --stage2=${STAGE2}
22-
--libpppwn=$<TARGET_FILE:${PROJECT_NAME}_shared>)
22+
--libpppwn=$<TARGET_FILE:${PROJECT_NAME}_shared>)
23+
24+
add_executable(${PROJECT_NAME}_output
25+
${CMAKE_CURRENT_SOURCE_DIR}/output.cpp
26+
${CMAKE_CURRENT_SOURCE_DIR}/extern.cpp)
27+
target_link_libraries(${PROJECT_NAME}_output PUBLIC ${PROJECT_NAME}_static)

tests/README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,10 @@ Test 2: Replace some functions in pppwn.py with C++ version, and run with a real
1919
cmake -B build -DBUILD_TEST=ON -DPython3_EXECUTABLE=$(which python3) -DIFACE=en10 -DFW=900 -DSTAGE1="<path>" -DSTAGE2="<path>"
2020
cmake --build build pppwn_pybind
2121
```
22+
23+
Test 3: Output the packet generated by the C++ version.
24+
25+
```shell
26+
cmake -B build -DBUILD_TEST=ON
27+
cmake --build build pppwn_output
28+
```

0 commit comments

Comments
 (0)