Version and Platform (required):
- Binary Ninja Version: [e.g. 4.0.4000-dev] (if version is stable, please also test the latest development build via the "Update Channel" option)
- Edition: Personal
- Tested on Linux and MacOS
- OS Version: Arch Linux, 26.4.1
- CPU Architecture: x64 & M1
Bug Description:
When looking at the pseudo objective-c view of a compiled binary the completion handler arguments are dropped.
Original code:
- (void)URLSession:(NSURLSession *)session
didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge
completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential *))completionHandler {
if (![challenge.protectionSpace.authenticationMethod
isEqualToString:NSURLAuthenticationMethodServerTrust]) {
completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, nil);
return;
}
SecTrustRef trust = challenge.protectionSpace.serverTrust;
[self appendLog:[NSString stringWithFormat:@"TLS challenge from: %@",
challenge.protectionSpace.host]];
[self logCertificateChain:trust];
[self appendLog:@""];
[self appendLog:@"[No Chain Validation]"];
completionHandler(NSURLSessionAuthChallengeUseCredential,
[NSURLCredential credentialForTrust:trust]);
}
Steps To Reproduce:
Create a dummy application using the linked source
Compile and open in binary ninja
Select objective-c view
Navigate to "didReceiveChallenge"
Inspect result
For me it's:
100001944 void
100001944 -[Ex3_NoChainValidationViewController URLSession:didReceiveChallenge:completionHandler:]
100001944 (struct Ex3_NoChainValidationViewController* self, SEL sel, id URLSession,
100001944 id didReceiveChallenge, id completionHandler)
100001944 {
100001944 SEL sel_1 = sel;
10000196c id location_2 = nullptr;
100001970 _objc_storeStrong(&location_2, URLSession);
10000197c id location_1 = nullptr;
100001980 _objc_storeStrong(&location_1, didReceiveChallenge);
10000198c id location = nullptr;
100001990 _objc_storeStrong(&location, completionHandler);
1000019a4 id obj = [[location_1 protectionSpace] retain];
1000019b8 id obj_1 = [[obj authenticationMethod] retain];
1000019d0 int32_t x0_6 =
1000019d0 [obj_1 isEqualToString:*(uint64_t*)_NSURLAuthenticationMethodServerTrust];
1000019e8 [obj_1 release];
1000019f8 [obj release];
1000019f8
100001a00 if (x0_6 & 1)
100001a00 {
100001a30 id obj_2 = [[location_1 protectionSpace] retain];
100001a44 int64_t x0_12 = [obj_2 serverTrust];
100001a5c [obj_2 release];
100001a7c struct objc_class* const var_b0_1 = NSString;
100001a8c id obj_3 = [[location_1 protectionSpace] retain];
100001aa0 id obj_4 = [[obj_3 host] retain];
100001ab8 id obj_7 = obj_4;
100001acc int64_t obj_5 =
100001acc [[NSString stringWithFormat:@"TLS challenge from: %@"] retain];
100001ae0 [self appendLog:obj_5];
100001af0 [obj_5 release];
100001b00 [obj_4 release];
100001b10 [obj_3 release];
100001b20 [self logCertificateChain:x0_12];
100001b34 [self appendLog:&cfstr_];
100001b48 [self appendLog:@"[No Chain Validation]"];
100001b5c [self appendLog:@" WARNING: skipping ALL certificate validation."];
100001b70 [self appendLog:
100001b70 &cfstr___Any_cert_?_self-signed,_expired,_wrong_CA_?_is_accepted.];
100001b84 [self appendLog:@"
100001b84 Fully vulnerable to MITM attacks. Never use in production."];
100001b98 [self appendLog:@" => ACCEPTED (no checks performed)"];
100001ba0 id location_4 = location;
100001bbc id obj_6 = [[NSURLCredential credentialForTrust:x0_12] retain];
/*
The next line corresponds to:
completionHandler(NSURLSessionAuthChallengeUseCredential,
[NSURLCredential credentialForTrust:trust]);
But the credential object is never passed, only 0 is visible, which maps to NSURLSessionAuthChallengeUseCredential.
*/
100001bd4 (*(int64_t*)((char*)location_4 + 0x10))(location_4, 0);
100001be4 [obj_6 release];
100001be8 int32_t var_3c_1 = 0;
100001a00 }
100001a00 else
100001a00 {
/*
This one is more correct as NULL is passed as the final parameter
*/
100001a08 id location_3 = location;
100001a18 (*(int64_t*)((char*)location_3 + 0x10))(location_3, 1, 0);
100001a20 int32_t var_3c = 1;
100001a00 }
100001a00
100001bfc _objc_storeStrong(&location, nullptr);
100001c08 _objc_storeStrong(&location_1, nullptr);
100001c14 _objc_storeStrong(&location_2, nullptr);
100001944 }
Expected Behavior:
The parameter shouldn't just be dropped from the view, it appears as if it's unused but that cannot be the case, otherwise the test application would have errored out. Since it doesn't, the credential object must be passed.
Binary:
If applicable, please provide us with the binary to help us work with the issue faster. Here are a few options:
#import "Ex3_NoChainValidationViewController.h"
@interface Ex3_NoChainValidationViewController () <NSURLSessionDelegate>
@property (nonatomic, strong) NSURLSession *session;
@end
@implementation Ex3_NoChainValidationViewController
- (NSString *)exampleTitle {
return @"3. No Chain Validation";
}
- (NSString *)exampleDescription {
return @"DANGER";
}
- (NSString *)exampleURL {
return @"https://self-signed.badssl.com";
}
- (void)performRequest {
NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
self.session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:nil];
NSURL *url = [NSURL URLWithString:[self exampleURL]];
[[self.session dataTaskWithURL:url
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
[self handleHTTPResponse:response data:data error:error];
[self finishRequest];
[self.session invalidateAndCancel];
}] resume];
}
#pragma mark - NSURLSessionDelegate
- (void)URLSession:(NSURLSession *)session
didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge
completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential *))completionHandler {
if (![challenge.protectionSpace.authenticationMethod
isEqualToString:NSURLAuthenticationMethodServerTrust]) {
completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, nil);
return;
}
SecTrustRef trust = challenge.protectionSpace.serverTrust;
[self appendLog:[NSString stringWithFormat:@"TLS challenge from: %@",
challenge.protectionSpace.host]];
[self logCertificateChain:trust];
[self appendLog:@""];
[self appendLog:@"[No Chain Validation]"];
completionHandler(NSURLSessionAuthChallengeUseCredential,
[NSURLCredential credentialForTrust:trust]);
}
@end
Version and Platform (required):
Bug Description:
When looking at the pseudo objective-c view of a compiled binary the completion handler arguments are dropped.
Original code:
Steps To Reproduce:
Create a dummy application using the linked source
Compile and open in binary ninja
Select objective-c view
Navigate to "didReceiveChallenge"
Inspect result
For me it's:
Expected Behavior:
The parameter shouldn't just be dropped from the view, it appears as if it's unused but that cannot be the case, otherwise the test application would have errored out. Since it doesn't, the credential object must be passed.
Binary:
If applicable, please provide us with the binary to help us work with the issue faster. Here are a few options: