├── .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 | ![Sloth](https://github.com/grp/Paperback/blob/master/sloth.png?raw=true) 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 | --------------------------------------------------------------------------------