├── .gitignore
├── Entitlements.xml
├── LICENSE
├── README.md
├── build.ninja
├── bundle.ninja
├── insert_dylib.py
├── library.ninja
├── macho.py
├── rules.ninja
├── sloth.png
└── src
├── Feed.m
├── Hook.h
├── Keychain.m
├── Keys.m
└── NUX.m
/.gitignore:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2016, Grant Paul
2 | # All rights reserved.
3 | #
4 | # Redistribution and use in source and binary forms, with or without
5 | # modification, are permitted provided that the following conditions are met:
6 | #
7 | # 1. Redistributions of source code must retain the above copyright notice, this
8 | # list of conditions and the following disclaimer.
9 | # 2. Redistributions in binary form must reproduce the above copyright notice,
10 | # this list of conditions and the following disclaimer in the documentation
11 | # and/or other materials provided with the distribution.
12 | #
13 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
14 | # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15 | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16 | # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
17 | # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18 | # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19 | # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
20 | # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
22 | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 |
24 | .DS_Store
25 |
26 | Paper.app/
27 | _CodeSignature/
28 |
29 | build/
30 | *.pyc
31 |
--------------------------------------------------------------------------------
/Entitlements.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | application-identifier
7 | XZ7P2T9SKD.com.grantpaul.Paperback
8 |
9 |
10 | get-task-allow
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2016, Grant Paul
2 | All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions are met:
6 |
7 | 1. Redistributions of source code must retain the above copyright notice, this
8 | list of conditions and the following disclaimer.
9 | 2. Redistributions in binary form must reproduce the above copyright notice,
10 | this list of conditions and the following disclaimer in the documentation
11 | and/or other materials provided with the distribution.
12 |
13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
14 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
17 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
20 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
22 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Paperback
2 |
3 | A version of Paper modified to pretend to be the Facebook app.
4 |
5 | ## Explanation
6 |
7 | Paper was an alternative to the Facebook app released in February 2014 and discontinued in July 2016. While the app was disabled remotely, the client is still functional. This project brings Paper back to life by making it indistinguishable from the standard Facebook for iOS app.
8 |
9 | ## Installation
10 |
11 | ### Prequisites
12 |
13 | - Recent macOS and Xcode.
14 | - [Ninja](https://ninja-build.org) to build:
15 |
16 | brew install ninja
17 |
18 | - [ios-deploy](https://github.com/phonegap/ios-deploy) to install:
19 |
20 | brew install node
21 | npm install -g ios-deploy
22 |
23 | - An unmodified, decrypted copy of `Paper.app`, version 1.2.6.
24 | - An iOS Developer program membership, to re-sign the app.
25 |
26 | ### Instructions
27 |
28 | 1. Put the decrypted `Paper.app` into the same directory as the code.
29 | 2. Modify `Entitlements.xml` to reference the appropriate App ID prefix for your provisioning profile.
30 | 3. Set the `CODE_SIGN_IDENTITY` environment variable to reference the appropriate code signing identity (often `iPhone Developer`).
31 |
32 | export CODE_SIGN_IDENTITY="iPhone Developer"
33 |
34 | 4. Build:
35 |
36 | ninja build
37 |
38 | 5. Install onto attached device:
39 |
40 | ninja install
41 |
42 | Alternatively, package `build/Paper.app` and install with iTunes or OTA.
43 |
44 | ## License
45 |
46 | See the `LICENSE` file for details.
47 |
48 | ---
49 |
50 | 
51 |
52 | Thanks to everyone who made Paper possible.
53 |
54 |
--------------------------------------------------------------------------------
/build.ninja:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2016, Grant Paul
2 | # All rights reserved.
3 | #
4 | # Redistribution and use in source and binary forms, with or without
5 | # modification, are permitted provided that the following conditions are met:
6 | #
7 | # 1. Redistributions of source code must retain the above copyright notice, this
8 | # list of conditions and the following disclaimer.
9 | # 2. Redistributions in binary form must reproduce the above copyright notice,
10 | # this list of conditions and the following disclaimer in the documentation
11 | # and/or other materials provided with the distribution.
12 | #
13 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
14 | # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15 | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16 | # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
17 | # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18 | # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19 | # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
20 | # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
22 | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 |
24 | include rules.ninja
25 |
26 | # Build directory.
27 | builddir = build
28 | build clean: rm ${builddir}
29 |
30 | # Build app bundle.
31 | bundle = ${builddir}/Paper.app
32 | subninja bundle.ninja
33 |
34 | # Build injected library.
35 | library = ${bundle}/Paperback.dylib
36 | subninja library.ninja
37 |
38 | # Default build.
39 | build build: phony bundle library
40 | default build
41 |
42 | # Sign and install.
43 | identity = $$(echo $$CODE_SIGN_IDENTITY)
44 | entitlements = Entitlements.xml
45 |
46 | build sign-library: codesign ${library} | ${entitlements} build
47 | identity = ${identity}
48 | entitlements = ${entitlements}
49 | build sign-bundle: codesign ${bundle} | ${entitlements} build
50 | identity = ${identity}
51 | entitlements = ${entitlements}
52 | build sign: phony sign-library sign-bundle
53 |
54 | build install: deploy ${bundle} | sign
55 | flags =
56 | build debug: deploy ${bundle} | sign
57 | flags = -d
58 |
--------------------------------------------------------------------------------
/bundle.ninja:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2016, Grant Paul
2 | # All rights reserved.
3 | #
4 | # Redistribution and use in source and binary forms, with or without
5 | # modification, are permitted provided that the following conditions are met:
6 | #
7 | # 1. Redistributions of source code must retain the above copyright notice, this
8 | # list of conditions and the following disclaimer.
9 | # 2. Redistributions in binary form must reproduce the above copyright notice,
10 | # this list of conditions and the following disclaimer in the documentation
11 | # and/or other materials provided with the distribution.
12 | #
13 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
14 | # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15 | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16 | # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
17 | # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18 | # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19 | # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
20 | # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
22 | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 |
24 | build ${bundle}: copy Paper.app
25 |
26 | plist = ${bundle}/Info.plist
27 | build ${plist}: sh | ${bundle}
28 | # Change the bundle identifier to match the entitlements.
29 | cmd = plutil -replace "CFBundleIdentifier" -string "com.grantpaul.Paperback" "${plist}"
30 | desc = Modify Info.plist
31 |
32 | binary = ${bundle}/Paper
33 | build ${binary}: sh | ${bundle} insert_dylib.py macho.py
34 | # Add the load command to load the library.
35 | cmd = python insert_dylib.py --input "${binary}" --output "${binary}" --dylib "@executable_path/Paperback.dylib"
36 | desc = Add library load command
37 |
38 | build bundle: phony ${bundle} ${plist} ${binary}
39 |
--------------------------------------------------------------------------------
/insert_dylib.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2016, Grant Paul
2 | # All rights reserved.
3 | #
4 | # Redistribution and use in source and binary forms, with or without
5 | # modification, are permitted provided that the following conditions are met:
6 | #
7 | # 1. Redistributions of source code must retain the above copyright notice, this
8 | # list of conditions and the following disclaimer.
9 | # 2. Redistributions in binary form must reproduce the above copyright notice,
10 | # this list of conditions and the following disclaimer in the documentation
11 | # and/or other materials provided with the distribution.
12 | #
13 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
14 | # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15 | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16 | # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
17 | # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18 | # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19 | # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
20 | # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
22 | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 |
24 | import sys
25 | import struct
26 | import argparse
27 |
28 | import macho
29 |
30 | def insert_dylib_macho(contents, dylib, offset=0):
31 | initial_offset = offset
32 |
33 | big_magic, = struct.unpack_from('>I', contents, offset)
34 | little_magic, = struct.unpack_from('I', contents, offset)
135 | little_magic, = struct.unpack_from('
27 |
28 | #import "Hook.h"
29 |
30 |
31 | @interface FBGraphQLQuery : NSObject
32 |
33 | - (NSString *)queryString;
34 | - (void)setQueryString:(NSString *)queryString;
35 |
36 | @end
37 |
38 | @interface FBNetworkerRequest : NSObject
39 |
40 | @end
41 |
42 | @interface FBSessionNetworkerRequest : FBNetworkerRequest
43 |
44 | @end
45 |
46 | @interface FBGraphQLDownloadRequest : FBSessionNetworkerRequest
47 |
48 | @end
49 |
50 | @interface FBGraphQLPagedDownloadRequest : FBGraphQLDownloadRequest
51 |
52 | @end
53 |
54 | @interface FBNewsFeedSectionStoryDownloadRequest : FBGraphQLPagedDownloadRequest
55 |
56 | - (FBGraphQLQuery *)newQueryWithCursor:(id)cursor;
57 |
58 | @end
59 |
60 | @interface FBNewsFeedSectionStreamConfiguration : NSObject
61 |
62 | - (NSString *)storySectionNameForSequenceType:(unsigned int)type;
63 |
64 | @end
65 |
66 | __attribute__((constructor))
67 | static void FeedInitialize(void)
68 | {
69 | Hook(NSClassFromString(@"FBNewsFeedSectionStoryDownloadRequest"), @selector(newQueryWithCursor:), ^(FBNewsFeedSectionStoryDownloadRequest *self, id cursor) {
70 | FBGraphQLQuery *query = Original(cursor);
71 |
72 | NSString *queryString = query.queryString;
73 |
74 | /*
75 | * Rather than loading a Paper section feed, load the standard News Feed
76 | * used by other Facebook apps.
77 | */
78 | NSRange sectionFeedRange = [queryString rangeOfString:@"section_feed"];
79 | queryString = [queryString stringByReplacingCharactersInRange:sectionFeedRange withString:@"news_feed"];
80 |
81 | /* `news_feed` is a field on `Viewer`, not a Paper section. */
82 | NSRange nodeRange = [queryString rangeOfString:@"node()"];
83 | queryString = [queryString stringByReplacingCharactersInRange:nodeRange withString:@"viewer()"];
84 |
85 | /* `Viewer` does not have an ID. */
86 | NSRange idRange = [queryString rangeOfString:@"cache_id,id,"];
87 | queryString = [queryString stringByReplacingCharactersInRange:idRange withString:@""];
88 |
89 | /*
90 | * Use the Facebook app environment, rather than Paper.
91 | */
92 | NSRange immersiveRange = [queryString rangeOfString:@"iphone_immersive"];
93 | queryString = [queryString stringByReplacingCharactersInRange:immersiveRange withString:@"iphone"];
94 |
95 | query.queryString = queryString;
96 |
97 | /*
98 | * Swap out the root call and ID to match the modified query.
99 | */
100 | [query setValue:@"viewer" forKey:@"callName"];
101 | [query setValue:nil forKey:@"rootIDVariable"];
102 |
103 | /*
104 | * Remove the persisted query ID so the request uses the query string,
105 | * rather than sending just the ID and assuming the query is cached.
106 | */
107 | [query setValue:nil forKey:@"persistID"];
108 |
109 | return query;
110 | });
111 |
112 | Hook(NSClassFromString(@"FBNewsFeedSectionStreamConfiguration"), @selector(storySectionNameForSequenceType:), ^(FBNewsFeedSectionStreamConfiguration *self, unsigned int type) {
113 | /*
114 | * The stories are loaded from the `news_feed` field on `Viewer`. This tells
115 | * Paper to find the stories in that field, rather than the `section_feed`.
116 | */
117 | return @"newsFeed";
118 | });
119 | }
120 |
121 |
--------------------------------------------------------------------------------
/src/Hook.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016, Grant Paul
3 | * All rights reserved.
4 | *
5 | * Redistribution and use in source and binary forms, with or without
6 | * modification, are permitted provided that the following conditions are met:
7 | *
8 | * 1. Redistributions of source code must retain the above copyright notice, this
9 | * list of conditions and the following disclaimer.
10 | * 2. Redistributions in binary form must reproduce the above copyright notice,
11 | * this list of conditions and the following disclaimer in the documentation
12 | * and/or other materials provided with the distribution.
13 | *
14 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
15 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
18 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
21 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 | */
25 |
26 | #import
27 |
28 | #define Hook(_class, _selector, ...) do { \
29 | SEL __selector = _selector; \
30 | Class __class = _class; \
31 | Method __method = class_getInstanceMethod(__class, __selector); \
32 | \
33 | /* Store implementations to swap. */ \
34 | __block IMP __original = NULL; \
35 | IMP __replaced = NULL; \
36 | { \
37 | /* Expose _cmd, lost by `imp_implementationWithBlock()`. */ \
38 | SEL _cmd = __selector; \
39 | __replaced = imp_implementationWithBlock(__VA_ARGS__); \
40 | } \
41 | \
42 | /* Perform the swap. */ \
43 | __original = method_setImplementation(__method, __replaced); \
44 | } while (0)
45 |
46 | #define Original(...) __original(self, _cmd, ##__VA_ARGS__)
47 |
48 |
--------------------------------------------------------------------------------
/src/Keychain.m:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016, Grant Paul
3 | * All rights reserved.
4 | *
5 | * Redistribution and use in source and binary forms, with or without
6 | * modification, are permitted provided that the following conditions are met:
7 | *
8 | * 1. Redistributions of source code must retain the above copyright notice, this
9 | * list of conditions and the following disclaimer.
10 | * 2. Redistributions in binary form must reproduce the above copyright notice,
11 | * this list of conditions and the following disclaimer in the documentation
12 | * and/or other materials provided with the distribution.
13 | *
14 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
15 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
18 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
21 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 | */
25 |
26 | #import
27 | #import
28 |
29 | #import "Hook.h"
30 |
31 |
32 | @interface FBKeychainItem : NSObject
33 |
34 | @end
35 |
36 | @interface FBKeychainStore : NSObject
37 |
38 | + (NSDictionary *)defaultDictionaryForItem:(FBKeychainItem *)item;
39 | + (NSDictionary *)searchDictionaryForItem:(FBKeychainItem *)item;
40 |
41 | @end
42 |
43 |
44 | static NSDictionary *
45 | RemoveKeychainGroup(NSDictionary *dict)
46 | {
47 | /*
48 | * By default, the access group is hardcoded to the Facebook app store
49 | * group. Since this app is re-signed, it can't access the Facebook group,
50 | * so should fall back to the app's keychain rather than a shared keychain.
51 | */
52 | NSMutableDictionary *removed = [dict mutableCopy];
53 | [removed removeObjectForKey:(__bridge NSString *)kSecAttrAccessGroup];
54 | return removed;
55 | }
56 |
57 | __attribute__((constructor))
58 | static void KeychianInitialize(void)
59 | {
60 | /*
61 | * Remove the key group from the keychain storage.
62 | */
63 | Hook(object_getClass(NSClassFromString(@"FBKeychainStore")), @selector(defaultDictionaryForItem:), ^(Class self, FBKeychainItem *item) {
64 | NSDictionary *original = Original(item);
65 | return RemoveKeychainGroup(original);
66 | });
67 |
68 | /*
69 | * Remove the key group from the keychain search.
70 | */
71 | Hook(object_getClass(NSClassFromString(@"FBKeychainStore")), @selector(searchDictionaryForItem:), ^(Class self, FBKeychainItem *item) {
72 | NSDictionary *original = Original(item);
73 | return RemoveKeychainGroup(original);
74 | });
75 | }
76 |
77 |
--------------------------------------------------------------------------------
/src/Keys.m:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016, Grant Paul
3 | * All rights reserved.
4 | *
5 | * Redistribution and use in source and binary forms, with or without
6 | * modification, are permitted provided that the following conditions are met:
7 | *
8 | * 1. Redistributions of source code must retain the above copyright notice, this
9 | * list of conditions and the following disclaimer.
10 | * 2. Redistributions in binary form must reproduce the above copyright notice,
11 | * this list of conditions and the following disclaimer in the documentation
12 | * and/or other materials provided with the distribution.
13 | *
14 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
15 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
18 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
21 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 | */
25 |
26 | #import
27 |
28 | #import "Hook.h"
29 |
30 |
31 | @interface FBCajmereKeySource : NSObject
32 |
33 | @property(readonly, copy, nonatomic) NSString *appSecret;
34 | @property(readonly, copy, nonatomic) NSString *publicAppName;
35 |
36 | @end
37 |
38 | @interface FBApplication : NSObject
39 |
40 | + (NSString *)applicationFBID;
41 |
42 | @end
43 |
44 |
45 | __attribute__((constructor))
46 | static void KeysInitialize(void)
47 | {
48 | /*
49 | * Replace Paper's app ID with the Facebook app ID.
50 | */
51 | Hook(object_getClass(NSClassFromString(@"FBApplication")), @selector(applicationFBID), ^(Class self) {
52 | /*
53 | * By default, this is read from the `FacebookAppID` key in the app's
54 | * Info.plist. However, it's cleaner to modify that at runtime rather
55 | * than on disk at build time, so hook the code here that loads it.
56 | */
57 | return @"6628568379";
58 | });
59 |
60 | /*
61 | * Replace Paper app secret with Facebook app secret.
62 | */
63 | Hook(NSClassFromString(@"FBCajmereKeySource"), @selector(appSecret), ^(FBCajmereKeySource *self) {
64 | return @"c1e620fa708a1d5696fb991c1bde5662";
65 | });
66 |
67 | /*
68 | * Replace Paper's user-agent name, with the Facebook app's user-agent name.
69 | */
70 | Hook(NSClassFromString(@"FBCajmereKeySource"), @selector(publicAppName), ^(FBCajmereKeySource *self) {
71 | /*
72 | * The history behind this one is interesting. The Facebook backend uses the
73 | * user-agent to identify the client app requesting the page. Originally, Paper
74 | * used its own codename for its user-agent, but since it's also sent to web
75 | * links viewed in Paper, this was seen as a potential for leaks. To hide Paper
76 | * before launch, the user-agent name was changed to `FBiOS`, distinguishable
77 | * on the server (in case) from the main app's `FBIOS` but inconspicuous to humans.
78 | */
79 | return @"FBIOS";
80 | });
81 | }
82 |
83 |
--------------------------------------------------------------------------------
/src/NUX.m:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016, Grant Paul
3 | * All rights reserved.
4 | *
5 | * Redistribution and use in source and binary forms, with or without
6 | * modification, are permitted provided that the following conditions are met:
7 | *
8 | * 1. Redistributions of source code must retain the above copyright notice, this
9 | * list of conditions and the following disclaimer.
10 | * 2. Redistributions in binary form must reproduce the above copyright notice,
11 | * this list of conditions and the following disclaimer in the documentation
12 | * and/or other materials provided with the distribution.
13 | *
14 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
15 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
18 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
21 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 | */
25 |
26 | #import
27 | #import
28 |
29 | #import "Hook.h"
30 |
31 |
32 | @interface FBCoverChooserView : UIView
33 |
34 | @property(readonly, nonatomic, getter=isInteracting) BOOL interacting;
35 |
36 | @end
37 |
38 | @interface FBFeedStoreView : FBCoverChooserView
39 |
40 | - (void)_doneButtonTapped:(id)sender;
41 | - (void)animateOut;
42 |
43 | @end
44 |
45 |
46 | __attribute__((constructor))
47 | static void NUXInitialize(void)
48 | {
49 | /*
50 | * Remove requirement to select a section before existing the feed store NUX,
51 | * since sections are no longer available.
52 | */
53 | Hook(NSClassFromString(@"FBFeedStoreView"), @selector(_doneButtonTapped:), ^(FBFeedStoreView *self, id sender) {
54 | /* Avoid checking if no covers are selected. */
55 | if (!self.interacting) {
56 | [self animateOut];
57 | }
58 | });
59 | }
60 |
61 |
--------------------------------------------------------------------------------