Skip to content

Commit

Permalink
Rewrote PingSpoof module. (CCBlueX#1449)
Browse files Browse the repository at this point in the history
This was tested on the Karhu test server and on servers that use the Polar anti-cheat.

Spoofs ping more properly than before.
  • Loading branch information
mems01 authored Oct 22, 2023
1 parent b306a48 commit cb633fe
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,66 +7,85 @@ package net.ccbluex.liquidbounce.features.module.modules.exploit

import net.ccbluex.liquidbounce.event.EventTarget
import net.ccbluex.liquidbounce.event.PacketEvent
import net.ccbluex.liquidbounce.event.UpdateEvent
import net.ccbluex.liquidbounce.event.TickEvent
import net.ccbluex.liquidbounce.event.WorldEvent
import net.ccbluex.liquidbounce.features.module.Module
import net.ccbluex.liquidbounce.features.module.ModuleCategory
import net.ccbluex.liquidbounce.utils.PacketUtils.sendPacket
import net.ccbluex.liquidbounce.utils.timing.TimeUtils.randomDelay
import net.ccbluex.liquidbounce.utils.PacketUtils.handlePacket
import net.ccbluex.liquidbounce.value.IntegerValue
import net.minecraft.network.Packet
import net.minecraft.network.play.client.C00PacketKeepAlive
import net.minecraft.network.play.client.C0FPacketConfirmTransaction
import net.minecraft.network.play.client.C16PacketClientStatus
import net.minecraft.network.play.server.S00PacketKeepAlive
import net.minecraft.network.play.server.S32PacketConfirmTransaction
import java.util.concurrent.ConcurrentHashMap

object PingSpoof : Module("PingSpoof", ModuleCategory.EXPLOIT) {

private val maxDelayValue: IntegerValue = object : IntegerValue("MaxDelay", 1000, 0..5000) {
override fun onChange(oldValue: Int, newValue: Int) = newValue.coerceAtLeast(minDelay)
private val delay by object : IntegerValue("Delay", 500, 0..25000) {
override fun onChange(oldValue: Int, newValue: Int): Int {
reset()

return newValue
}
}
private val maxDelay by maxDelayValue

private val minDelay by object : IntegerValue("MinDelay", 500, 0..5000) {
override fun onChange(oldValue: Int, newValue: Int) = newValue.coerceAtMost(maxDelay)
private val packetQueue = ConcurrentHashMap<Packet<*>, Pair<Long, Long>>()

override fun isSupported() = !maxDelayValue.isMinimal()
}
private var cancelPackets = false

private val packetQueue = hashMapOf<Packet<*>, Long>()
override fun onEnable() {
cancelPackets = true
}

override fun onDisable() = packetQueue.clear()
override fun onDisable() {
reset()
}

@EventTarget
// Ignore conditions must be true because there is always a chance packets could be received
// during module disable and the packet queue would not fetch the latest packet addition, therefore messing up the order
@EventTarget(ignoreCondition = true)
fun onPacket(event: PacketEvent) {
val packet = event.packet

if (mc.thePlayer == null) {
if (mc.thePlayer == null || !cancelPackets) {
return
}

if ((packet is C00PacketKeepAlive || packet is C16PacketClientStatus || packet is C0FPacketConfirmTransaction) && packet !in packetQueue) {
if (packet is S32PacketConfirmTransaction || packet is S00PacketKeepAlive) {
event.cancelEvent()

synchronized(packetQueue) {
packetQueue[packet] =
System.currentTimeMillis() + randomDelay(minDelay, maxDelay)
}
// Use nano time for the registration time since there are chances
// the packets can be under the same milliseconds and mess up the order
packetQueue[packet] = System.currentTimeMillis() + delay to System.nanoTime()
}
}

@EventTarget
fun onUpdate(event: UpdateEvent) {
var filtered: List<Packet<*>>
fun onTick(event: TickEvent) {
sendPacketsByOrder(false)
}

@EventTarget
fun onWorld(event: WorldEvent) {
packetQueue.clear()
}

synchronized(packetQueue) {
filtered = packetQueue.entries.filter {
it.value <= System.currentTimeMillis()
}.map { it.key }
}
private fun sendPacketsByOrder(all: Boolean) {
// Accept packets that have passed the requested delay, then sort by registration time
val filtered = packetQueue.filter {
all || it.value.first <= System.currentTimeMillis()
}.entries.sortedBy { it.value.second }.map { it.key }

for (packet in filtered) {
sendPacket(packet)
handlePacket(packet)
packetQueue.remove(packet)
}
}

private fun reset() {
sendPacketsByOrder(true)

packetQueue.clear()

cancelPackets = false
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ object PacketUtils : MinecraftInstance() {
fun sendPackets(vararg packets: Packet<*>, triggerEvents: Boolean = true) =
packets.forEach { sendPacket(it, triggerEvents) }

fun handlePacket(packet: Packet<INetHandlerPlayClient>?) = packet?.processPacket(mc.netHandler)
fun handlePacket(packet: Packet<*>?) = (packet as Packet<INetHandlerPlayClient>).processPacket(mc.netHandler)

val Packet<*>.type
get() = when (this.javaClass.simpleName[0]) {
Expand Down

0 comments on commit cb633fe

Please sign in to comment.