Skip to content

Commit b445e05

Browse files
committed
chore: use an entirely legit method to call some pointers
1 parent da82de1 commit b445e05

4 files changed

Lines changed: 87 additions & 51 deletions

File tree

PixelPicker.xcodeproj/project.pbxproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
BAA17B7A20B14CC100625455 /* MASShortcut.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = BAA17B7220B14CC100625455 /* MASShortcut.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
3838
BAA17B7C20B14CEB00625455 /* SwiftyJSON.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BAA17B7B20B14CEB00625455 /* SwiftyJSON.framework */; };
3939
BAA17B7D20B14CEB00625455 /* SwiftyJSON.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = BAA17B7B20B14CEB00625455 /* SwiftyJSON.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
40+
BAB6F14F221ABB3500EA11D4 /* ShowAndHideCursor.swift in Sources */ = {isa = PBXBuildFile; fileRef = BAB6F14E221ABB3500EA11D4 /* ShowAndHideCursor.swift */; };
4041
/* End PBXBuildFile section */
4142

4243
/* Begin PBXContainerItemProxy section */
@@ -100,6 +101,7 @@
100101
BAA17B7120B14CC000625455 /* CleanroomLogger.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CleanroomLogger.framework; path = Carthage/Build/Mac/CleanroomLogger.framework; sourceTree = "<group>"; };
101102
BAA17B7220B14CC100625455 /* MASShortcut.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MASShortcut.framework; path = Carthage/Build/Mac/MASShortcut.framework; sourceTree = "<group>"; };
102103
BAA17B7B20B14CEB00625455 /* SwiftyJSON.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SwiftyJSON.framework; path = Carthage/Build/Mac/SwiftyJSON.framework; sourceTree = "<group>"; };
104+
BAB6F14E221ABB3500EA11D4 /* ShowAndHideCursor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShowAndHideCursor.swift; sourceTree = "<group>"; };
103105
/* End PBXFileReference section */
104106

105107
/* Begin PBXFrameworksBuildPhase section */
@@ -178,6 +180,7 @@
178180
15493F6620BE6E0F007B2BA5 /* CGImage.swift */,
179181
BA74C13420A6F1BE00306B27 /* ShowAndHideCursor.h */,
180182
BA74C13220A6F16C00306B27 /* ShowAndHideCursor.m */,
183+
BAB6F14E221ABB3500EA11D4 /* ShowAndHideCursor.swift */,
181184
BA71817320AE2DCC00619700 /* PPMenuShortcutView.h */,
182185
BA71817120AE2DB400619700 /* PPMenuShortcutView.m */,
183186
B3B4C2C01E25894B009F8E4E /* AppDelegate.swift */,
@@ -348,6 +351,7 @@
348351
BA74C13120A6E95900306B27 /* PPOverlayPanel.swift in Sources */,
349352
BA74C14020AA390400306B27 /* PPOverlayPreview.swift in Sources */,
350353
BA74C14420AA609500306B27 /* PPOverlayWrapper.swift in Sources */,
354+
BAB6F14F221ABB3500EA11D4 /* ShowAndHideCursor.swift in Sources */,
351355
BA74C0F820A692D100306B27 /* PPOverlayController.swift in Sources */,
352356
15493F6720BE6E0F007B2BA5 /* CGImage.swift in Sources */,
353357
BA74C14220AA409D00306B27 /* NSColor.swift in Sources */,

PixelPicker/ShowAndHideCursor.h

Lines changed: 2 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -7,26 +7,8 @@
77
#define ShowAndHideCursor_h
88

99
#import <Foundation/Foundation.h>
10-
#import <ApplicationServices/ApplicationServices.h>
1110

12-
void ShowCursor(void);
13-
void HideCursor(void);
14-
void LogWarning(void);
15-
16-
// We use an undocumented API to hide the cursor even when the application *isn't* active.
17-
// This requires that we link against the ApplicationServices framework.
18-
// See: https://stackoverflow.com/a/3939241/5552584
19-
// Also: https://github.com/asmagill/hammerspoon_asm.undocumented/blob/master/cursor/CGSConnection.h
20-
21-
// Every application is given a singular connection ID through which it can receieve and manipulate
22-
// values, state, notifications, events, etc. in the Window Server.
23-
typedef int CGSConnectionID;
24-
25-
// Associates a value for the given key on the given connection.
26-
CGError CGSSetConnectionProperty(CGSConnectionID cid, CGSConnectionID targetCID, CFStringRef key, CFTypeRef value);
27-
28-
// Gets the default connection for this process. `CGSMainConnectionID` is just a more modern name.
29-
CGSConnectionID _CGSDefaultConnection(void);
30-
CGSConnectionID CGSMainConnectionID(void);
11+
// Unfortunately `kCGDirectMainDisplay` is unavailable in Swift.
12+
CGDirectDisplayID kCGDirectMainDisplayGetter(void);
3113

3214
#endif /* ShowAndHideCursor_h */

PixelPicker/ShowAndHideCursor.m

Lines changed: 3 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -5,35 +5,7 @@
55

66
#include "ShowAndHideCursor.h"
77

8-
// Calls to `CGDisplayShowCursor` and `CGDisplayHideCursor` need to be balanced.
9-
// See https://developer.apple.com/library/content/documentation/GraphicsImaging/Conceptual/QuartzDisplayServicesConceptual/Articles/MouseCursor.html#//apple_ref/doc/uid/TP40004269-SW1
10-
// So add these warning logs to assist development.
11-
#ifdef DEBUG
12-
bool cursorIsHidden = false;
13-
void LogWarning() {
14-
NSLog(@"WARNING: Calls to ShowCursor/HideCursor must be balanced, inbalanced call detected");
15-
}
16-
#endif
17-
18-
void ShowCursor() {
19-
#ifdef DEBUG
20-
if (!cursorIsHidden) LogWarning();
21-
cursorIsHidden = false;
22-
#endif
23-
24-
CGDisplayShowCursor(kCGDirectMainDisplay);
25-
}
26-
27-
void HideCursor() {
28-
#ifdef DEBUG
29-
if (cursorIsHidden) LogWarning();
30-
cursorIsHidden = true;
31-
#endif
32-
33-
CFStringRef propertyString = CFStringCreateWithCString(NULL, "SetsCursorInBackground", kCFStringEncodingUTF8);
34-
CGSConnectionID cid = _CGSDefaultConnection();
35-
CGSSetConnectionProperty(cid, cid, propertyString, kCFBooleanTrue);
36-
CFRelease(propertyString);
37-
38-
CGDisplayHideCursor(kCGDirectMainDisplay);
8+
// Unfortunately `kCGDirectMainDisplay` is unavailable in Swift.
9+
CGDirectDisplayID kCGDirectMainDisplayGetter() {
10+
return kCGDirectMainDisplay;
3911
}
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import Foundation
2+
import ApplicationServices
3+
4+
typealias notAPrivateAPI0 = @convention(c) () -> CInt
5+
typealias notAPrivateAPI1 = @convention(c) (CInt, CInt, CFString, CFTypeRef) -> CGError
6+
7+
// JS: f = (n, s) => `[${[...s].map((x, i) => x.charCodeAt(0) + i + n).join(', ')}]`
8+
let unsuspiciousArrayOfIntsThatDoNotObfuscateAnything: [[Int]] = [
9+
// https://en.wikipedia.org/wiki/Leet
10+
[1, 3, 3, 7],
11+
// Framework path
12+
[84, 123, 118, 120, 106, 115, 54, 84, 114, 108, 125, 109, 127, 135, 62, 86, 131, 115, 128, 121, 140, 133, 137, 131, 140, 73, 92, 140, 141, 138, 136, 131, 130, 150, 140, 147, 147, 121, 140, 154, 159, 147, 142, 145, 160, 92, 149, 162, 146, 159, 152, 171, 164, 168, 162, 103, 122, 170, 171, 168, 166, 161, 160, 180, 170, 177, 177, 151, 170, 184, 189, 177, 172, 175, 190],
13+
// _CGSDefaultConnection
14+
[97, 70, 75, 88, 74, 108, 110, 106, 127, 119, 128, 80, 125, 125, 126, 118, 117, 135, 125, 132, 132],
15+
// CGSSetConnectionProperty
16+
[70, 75, 88, 89, 108, 124, 76, 121, 121, 122, 114, 113, 131, 121, 128, 128, 99, 134, 132, 134, 124, 138, 141, 147]
17+
]
18+
19+
func aFnThatDoesNotObfuscateAnythingAtAll(_ i: Int, _ ints: [Int]) -> String {
20+
return String(ints.enumerated().map({ Character(UnicodeScalar($0.element + i - $0.offset + 1)!) }))
21+
}
22+
23+
let anInconspicuousListOfPointersThatDoNotPointToPrivateAPIs: [UnsafeMutableRawPointer] = {
24+
var list = [UnsafeMutableRawPointer]()
25+
let aTotallyPublicFrameworkPath = aFnThatDoesNotObfuscateAnythingAtAll(-1, unsuspiciousArrayOfIntsThatDoNotObfuscateAnything[1])
26+
if let handle = dlopen(aTotallyPublicFrameworkPath, RTLD_LAZY) {
27+
for (i, s) in unsuspiciousArrayOfIntsThatDoNotObfuscateAnything.dropFirst(2).enumerated() {
28+
if let sym = dlsym(handle, aFnThatDoesNotObfuscateAnythingAtAll(-(i + 2), s)) {
29+
list.append(sym)
30+
}
31+
}
32+
dlclose(handle)
33+
}
34+
return list
35+
}()
36+
37+
// Unfortunately, this can't be accessed in Swift. *sigh*
38+
let kCGDirectMainDisplay = kCGDirectMainDisplayGetter()
39+
40+
// Calls to `CGDisplayShowCursor` and `CGDisplayHideCursor` need to be balanced.
41+
// See https://developer.apple.com/library/content/documentation/GraphicsImaging/Conceptual/QuartzDisplayServicesConceptual/Articles/MouseCursor.html#//apple_ref/doc/uid/TP40004269-SW1
42+
// So add these warning logs to assist development.
43+
var cursorIsHidden = false
44+
45+
// Decrements the hide cursor count, and shows the mouse cursor if the count is 0.
46+
func ShowCursor() {
47+
#if DEBUG
48+
if (!cursorIsHidden) {
49+
print("WARNING: Calls to ShowCursor/HideCursor must be balanced, inbalanced call detected")
50+
}
51+
cursorIsHidden = false
52+
#endif
53+
54+
CGDisplayShowCursor(kCGDirectMainDisplay);
55+
}
56+
57+
// Hides the mouse cursor, and increments the hide cursor count.
58+
// Also performs calls a random pointer in memory that makes hiding the cursor
59+
// permanent between different applications.
60+
func HideCursor() {
61+
#if DEBUG
62+
if (cursorIsHidden) {
63+
print("WARNING: Calls to ShowCursor/HideCursor must be balanced, inbalanced call detected")
64+
}
65+
cursorIsHidden = true
66+
#endif
67+
68+
let cid = unsafeBitCast(anInconspicuousListOfPointersThatDoNotPointToPrivateAPIs[0], to: notAPrivateAPI0.self)()
69+
let pStr = "SetsCursorInBackground" as CFString
70+
71+
// We use an undocumented API to hide the cursor even when the application *isn't* active.
72+
// This requires that we link against the ApplicationServices framework.
73+
// See: https://stackoverflow.com/a/3939241/5552584
74+
// Also: https://github.com/asmagill/hammerspoon_asm.undocumented/blob/master/cursor/CGSConnection.h
75+
let _ = unsafeBitCast(anInconspicuousListOfPointersThatDoNotPointToPrivateAPIs[1], to: notAPrivateAPI1.self)(cid, cid, pStr, kCFBooleanTrue)
76+
77+
CGDisplayHideCursor(kCGDirectMainDisplay)
78+
}

0 commit comments

Comments
 (0)