Saturday, March 30, 2013

TiVo App - IPScanner

Now that I have the log and the disassembly, I want to figure out how the iOS application finds TiVo within the local area network...

iOS Application TiVo Scanner

Looking at the disassembly, the object "NetworkManager" is responsible for telling the "IPScanner" object to scan the network for TiVo's (There is a "NetworkBrowser" object that uses the bonjour service to find TiVo's but I did not decide to pursue this).  


Scanning Process:
  1. The function "startBrowser" on the NetworkManager object creates an instance of "IPScanner"
  2. The method "beginScan" on the IPScanner object is called
    1. Grabs the wifi address (XXX.XXX.XXX.XXX), omits the last "XXX"
    2. Passes this "XXX.XXX.XXX" address to the "testAddresses" method
      1. Iterate through all subnets in this IP block...
        1. Create a TCP Connection for the IP on port 443
        2. At some point, the "TcpConnectionOpenedForInput" method on IPScanner will be called by the TCP Connection.
        3. If connection is successful, store this host & then attempt to connect on port 31339
        4. While on the 443 connection, retrieve the SSL certificate from the host.  Retrieve the certificate description and set this as the "TSN" for this host. This value will be in the format XXX-YYYY-ZZZZ-UUUU.  The app parses out the UUUU and attempts to match up this value with a set of known TiVo certificate descriptions via OBJC_CLASS_$_NetworkManager.HardwareTypeFromBodyId()
        5. If port 31339 is enabled, it gets a callback and the app sets this host to have its property "HasRemote()" equal to true
High level overview:

;  - Scan all hosts in the last subnet, look for port 443
;  - If we find port 443, look for port 31339 for the same host (if found, setRemote=true)
;  - Once we have scanned all, inspect the SSL security certificate for each host
;  - If SSL Certificate matches getHardwareByBodyId() and certain criteria, determine the HardwareType
;   - If HardwareType = 4, HasMind=true
; - If HardwareType = 5, then it is a transcoder (TiVo Stream) and put into successTranscoders, remove it from the SuccessTCDS
;  - At the end of the day, *m_SuccessTranscoders & *m_SuccessTCDS will be populated, transcoders will not be in successTCDS, and non-tivos will not be in either.



Now that we know how it scans, let's figure out what it does once it finds a TiVo...



Disassembly & Comments


/*  147 */
struct NetworkManager
{
  uint8_t NSObject_opaque[4];
  struct TiVo_Reachability *m_wanReach;
  struct TiVo_Reachability *m_lanReach;
  struct NSMutableArray *m_delegateList;
  struct NetworkBrowser *m_videosBrowser;
  struct NetworkBrowser *m_beaconBrowser;
  struct NetworkBrowser *m_rpcBrowser;
  struct NetworkBrowser *m_remoteBrowser;
  struct NetworkBrowser *m_xcodeBrowser;
  struct LocalTivoInfo *m_connectingTiVo;
  struct LocalTivoInfo *m_connectingTiVoMindRpc;
  struct LocalTivoInfo *m_manualBeacon;
  struct LocalTivoInfo *m_manualMindRpc;
  struct TivoInfo *m_tivo;
  struct NSMutableArray *m_tivoList;
  struct NSMutableArray *m_manualTivoList;
  struct NSMutableArray *m_xcodeList;
  int m_connectionMode;
  int m_wanModeAuthReqId;
  int m_s3ModeAuthReqId;
  int m_lanModeAuthReqId;
  int m_anonymousAuthReqId;
  int m_lineupSearchReqId;
  int m_tokenAuthReqId;
  int m_makAuthReqId;
  int m_bodyConfigReqId;
  struct TvLineup *m_guestModeLineup;
  struct NSString *m_s3ModeTsn;
  struct UIAlertView *m_reconnectAlert;
  struct IPScanner *m_ipScanner;
  struct AuthenticationToken *m_authToken;
  struct NSTimer *m_scanningTimer;
  int m_scanningAttempt;
  struct RpcRequestHandler *m_requestHandler;
  struct RpcRequestHandler *m_debugRequestHandler;
  struct RpcRequestHandler *m_tokenRequestHandler;
  struct TcpRemote *m_s3TcpRemote;
  struct NSDate *m_enteredForegroundDate;
  struct NSDate *m_enteredBackgroundDate;
  struct NSString *m_ipAddressWhenBackgrounded;
  struct NSTimer *m_reconnectTimer;
  struct NSTimer *m_networkActivityTimer;
  char m_shutdownBonjourAfterScan;
  struct NSString *m_wanHost;
  int m_wanPort;
  char enableBonjour;
  char enableIPScan;
  char enableServerDiscovery;
  char overrideSupportedPlatform;
  char enableRpcLogging;
  char enableRpcPerfLogging;
};

/*  152 */
struct IPScanner
{
  uint8_t NSObject_opaque[4];
  struct NSMutableArray *m_connections;
  struct NSMutableArray *m_successTCDs;
  struct NSMutableArray *m_successTranscoders;
};

NetworkManager."startBrowsing"() calls IP_Scanner



; IP SCANNER

; id __cdecl __IPScanner init_(struct IPScanner *self, SEL)
__IPScanner_init_

; Calling SP:
; -0x04 ? R8 is stored here
; -0x08 ? _OBJC_CLASS_$_IPScanner is stored here
; -0x12 ? This value is passed as the objc_super in objc_msgSendSuper2(struct objc_super *super, SEL op, ...)

var_18= -0x18
var_14= -0x14
var_10= -0x10

PUSH            {R4-R7,LR} ; Push registers R4-R7 & the link register onto the stack
ADD             R7, SP, #0xC ; Add 0xC (d12) to the stack pointer and store the value in R7  
; TODO - Why did we offset from the stack pointer?
STR.W           R8, [SP,#0xC+var_10]! ; Store R8 on the stack (address -0x04), auto-increment the SP to -0x04
; Add (0xc + -0x10) = -0x04 [d12 - d16 = -d4] to the stack pointer, then store the value of R8 there
; NOTE: This is the 1st argument (descending) on the stack!
SUB             SP, SP, #8 ; Subtract 8 from the stack pointer, the SP is now -0x12
MOV             R2, (classRef_IPScanner_0 - 0xD9C8E) ; classRef_IPScanner_0
MOV             R1, (selRef_init - 0xD9C90) ; selRef_init
ADD             R2, PC ; classRef_IPScanner_0
ADD             R1, PC ; selRef_init ("init")
STR             R0, [SP,#0x18+var_18] ; Store R0 on the stack (address -0x12).
; Add (0x18 + -0x18) = 0x00 [d24 - d24 = d0] to the stack pointer, then store the value of R0 there
; NOTE: This is the 4th argument (descending) on the stack!
LDR             R0, [R2] ; _OBJC_CLASS_$_IPScanner
LDR             R1, [R1] ; "init"
STR             R0, [SP,#0x18+var_14] ; Store R0 (_OBJC_CLASS_$_IPScanner) on the stack (address -0x08)
; Add (0x18 + -0x14) = 0x04 [d24 - d20 = d4] to the stack pointer, then store the address in R0
; NOTE: This is the 3rd argument (descending) on the stack!
; TOOD: This method does not appear to do anything since R0 is immediately overwritten?
MOV             R0, SP ; Copy the stack pointer (-0x12) to R0
BLX             _objc_msgSendSuper2 ; OBJC_EXPORT id objc_msgSendSuper2(struct objc_super *super [R0], SEL op, ... [R1])
; NOTE: This will return the memory pointer to the object we created
MOV             R4, R0 ; Copy R0 to R4
CMP             R4, #0 ; Compare R4 to 0
BEQ             loc_D9D24 ; If R4 is 0, branch (this is probably a null check)


; On success:
; Allocate a mutable array with initial capacity of 0, store the memory pointer to this mutable array in offset 0x04 of the IPScanner memory pointer (object property *m_connections)
; Allocate a mutable array with initial capacity of 2, store the memory pointer to this mutable array in offset 0x08 of the IPScanner memory pointer (object property *m_successTCDs)
; Allocate a mutable array with initial capacity of 1, store the memory pointer to this mutable array in offset 0x0C of the IPScanner memory pointer (object property *m_successTranscoders)






; IPScanner - (void)beginScan
; Attributes: bp-based frame

; void __cdecl __IPScanner beginScan_(struct IPScanner *self, SEL)
__IPScanner_beginScan_

PUSH            {R4-R7,LR} ;
ADD             R7, SP, #0xC ;
PUSH.W          {R8,R10,R11} ;
SUB             SP, SP, #8 ;
MOV             R11, R0 ;
; Clear all instances from *m_successTCDS
MOV             R0, (_OBJC_IVAR_$_IPScanner.m_successTCDs - 0xD9EC8) ; NSMutableArray *m_successTCDs;
MOVW            R1, #0x4E1E ;
ADD             R0, PC  ; NSMutableArray *m_successTCDs; ;
MOVT.W          R1, #0x45 ;
ADD             R1, PC ; selRef_removeAllObjects ;
LDR             R0, [R0] ; NSMutableArray *m_successTCDs; ;
LDR             R5, [R1] ; "removeAllObjects" ;
LDR.W           R0, [R11,R0] ;
MOV             R1, R5 ;
BLX             _objc_msgSend ;
; Clear all instances from *m_successTranscoders
MOVW            R0, #0xB330 ;
MOV             R1, R5
MOVT.W          R0, #0x4A
ADD             R0, PC  ; NSMutableArray *m_successTranscoders;
LDR             R0, [R0] ; NSMutableArray *m_successTranscoders;
LDR.W           R0, [R11,R0]
BLX             _objc_msgSend
; Clear all instances from *m_connections
MOVW            R0, #0xB312
MOV             R1, R5
MOVT.W          R0, #0x4A
ADD             R0, PC  ; NSMutableArray *m_connections;
LDR             R0, [R0] ; NSMutableArray *m_connections;
LDR.W           R0, [R11,R0]
BLX             _objc_msgSend
; Retrieve the "wifiIPAddress" and set its value to R5
MOV             R0, (selRef_wifiIPAddress - 0xD9F12) ; selRef_wifiIPAddress
ADD             R0, PC ; selRef_wifiIPAddress
LDR             R1, [R0] ; "wifiIPAddress"
MOV             R0, R11
BLX             _objc_msgSend
MOV             R5, R0
; Logging, pass our "wifiIPAddress" along
MOV             R0, (cfstr_IpScannerStart - 0xD9F28) ; "IP SCANNER: Starting IP Address:%@"
MOV             R1, R5
ADD             R0, PC  ; "IP SCANNER: Starting IP Address:%@"
BLX             _NSLog
; Split the "wifiIPAddress" value by ".", store the result in R6
MOV             R0, (selRef_componentsSeparatedByString_ - 0xD9F3A) ; selRef_componentsSeparatedByString_
MOVW            R2, #0xE0B8
ADD             R0, PC ; selRef_componentsSeparatedByString_
MOVT.W          R2, #0x4A
ADD             R2, PC  ; "."
LDR             R1, [R0] ; "componentsSeparatedByString:"
MOV             R0, R5
BLX             _objc_msgSend
MOV             R6, R0
; Retrieve the count of the split, If it does not have 4 parts, branch
MOV             R0, (selRef_count - 0xD9F54) ; selRef_count
ADD             R0, PC ; selRef_count
LDR             R1, [R0] ; "count"
MOV             R0, R6
BLX             _objc_msgSend
CMP             R0, #4
BNE             loc_D9FC0

; if(String.Split(WifiIPAddress,".") == 4){
WifiIPAddress_in_X.X.X._format
; Retrieve value at index [0] in the array created by the String.Split(), store it in R10
MOVW            R1, #0xAE54
MOVS            R2, #0
MOVT.W          R1, #0x45
MOV             R0, (selRef_objectAtIndex_ - 0xD9F76) ; selRef_objectAtIndex_
ADD             R1, PC ; classRef_NSString
ADD             R0, PC ; selRef_objectAtIndex_
LDR.W           R8, [R1] ; _OBJC_CLASS_$_NSString
LDR             R5, [R0] ; "objectAtIndex:"
MOV             R0, R6
MOV             R1, R5
BLX             _objc_msgSend
MOV             R10, R0
; Retrieve value at index [1] in the array created by the String.Split(), store it in R4
MOV             R0, R6
MOV             R1, R5
MOVS            R2, #1
BLX             _objc_msgSend
MOV             R4, R0
; Retrieve value at index [2] in the array created by the String.Split(), store it in R5
MOV             R0, R6
MOV             R1, R5
MOVS            R2, #2
BLX             _objc_msgSend
MOV             R5, R0
; Call NSString.StringWithFormat("%@.%@.%@.",), store its value in R5
MOV             R0, (selRef_stringWithFormat_ - 0xD9FAC) ; selRef_stringWithFormat_
MOVW            R2, #0x47D6
ADD             R0, PC ; selRef_stringWithFormat_
MOVT.W          R2, #0x4B
ADD             R2, PC  ; "%@.%@.%@."
MOV             R3, R10 ; First parameter of StringWithFormat is R3, which is our index [0]
LDR             R1, [R0] ; "stringWithFormat:"
MOV             R0, R8
STRD.W          R4, R5, [SP] ; Push R4 (index [1]) & R5 (index [2]) onto the stack
BLX             _objc_msgSend
MOV             R5, R0
; }
; At this point, our base IP address is stored in R5, assumed to be in the "X.X.X" format
loc_D9FC0
; Log our base ip address
MOVW            R0, #0x47CA
MOV             R1, R5
MOVT.W          R0, #0x4B
ADD             R0, PC  ; "IP SCANNER: Base IP Address:%@"
BLX             _NSLog
; Execute  IPScanner.testAddresses("X.X.X")
MOVW            R0, #0x7EE6
MOV             R2, R5
MOVT.W          R0, #0x45
ADD             R0, PC ; selRef_testAddresses_
LDR             R1, [R0] ; "testAddresses:"
MOV             R0, R11
ADD             SP, SP, #8
POP.W           {R8,R10,R11}
POP.W           {R4-R7,LR}
B.W             j__objc_msgSend
; End of function -[IPScanner beginScan]



; IPScanner - (void)testAddresses:(id)
; Attributes: bp-based frame

; void __cdecl __IPScanner testAddresses__(struct IPScanner *self, SEL, id)
__IPScanner_testAddresses__


; Local Variables:
__text:000D9DA8 Counter         = -0x3C
__text:000D9DA8 var_38          = -0x38
__text:000D9DA8 RefInit         = -0x34
__text:000D9DA8 RefSetDelegate  = -0x30
__text:000D9DA8 RefOpenWithHost = -0x2C
__text:000D9DA8 RefConnections  = -0x28
__text:000D9DA8 RefAddObject    = -0x24
__text:000D9DA8 RefRelease      = -0x20


; Parameter (id)
__text:000D9DA8 Id              = -0x1C ; PARAMETER


; Initialize references to things before we loop ...
__text:000D9DA8                 PUSH            {R4-R7,LR}
__text:000D9DAA                 ADD             R7, SP, #0xC
__text:000D9DAC                 PUSH.W          {R8,R10,R11}
__text:000D9DB0                 SUB             SP, SP, #0x24
__text:000D9DB2                 STR             R2, [SP,#0x3C+Id] ; Save our "id" in R2 to the stack
__text:000D9DB4                 MOV             R2, (_OBJC_IVAR_$_IPScanner.m_connections - 0xD9DCE) ; NSMutableArray *m_connections;
__text:000D9DBC                 MOV             R3, (selRef_addObject_ - 0xD9DE8) ; selRef_addObject_
__text:000D9DC4                 MOV             R5, R0
__text:000D9DC6                 MOVW            R0, #0x4F30
__text:000D9DCA                 ADD             R2, PC  ; NSMutableArray *m_connections;
__text:000D9DCC                 MOVT.W          R0, #0x45
__text:000D9DD0                 MOV             R4, (selRef_release - 0xD9DEA) ; selRef_release
__text:000D9DD8                 MOV             R1, (selRef_init - 0xD9DF2) ; selRef_init
__text:000D9DE0                 MOVW            R6, #0x5C64
__text:000D9DE4                 ADD             R3, PC ; selRef_addObject_
__text:000D9DE6                 ADD             R4, PC ; selRef_release
__text:000D9DE8                 MOVT.W          R6, #0x45
__text:000D9DEC                 ADD             R0, PC ; selRef_setDelegate_
__text:000D9DEE                 ADD             R1, PC ; selRef_init
__text:000D9DF0                 ADD             R6, PC ; selRef_openWithHost_port_SSLDesc_errorStr_
__text:000D9DF2                 LDR             R4, [R4] ; "release"
__text:000D9DF4                 MOV.W           R8, #0  ; Initialize counter loop to 0
__text:000D9DF8                 LDR             R3, [R3] ; "addObject:"
__text:000D9DFA                 LDR             R2, [R2] ; NSMutableArray *m_connections;
__text:000D9DFC                 STR             R3, [SP,#0x3C+RefAddObject]
__text:000D9DFE                 STR             R4, [SP,#0x3C+RefRelease]
__text:000D9E00                 STR             R2, [SP,#0x3C+RefConnections]
__text:000D9E02                 MOVW            R2, #0x4DB6
__text:000D9E06                 LDR             R3, [R6] ; "openWithHost:port:SSLDesc:errorStr:"
__text:000D9E08                 MOVT.W          R2, #0x45
__text:000D9E0C                 LDR             R0, [R0] ; "setDelegate:"
__text:000D9E0E                 ADD             R2, PC ; selRef_alloc
__text:000D9E10                 LDR             R1, [R1] ; "init"
__text:000D9E12                 STR             R3, [SP,#0x3C+RefOpenWithHost]
__text:000D9E14                 STR             R0, [SP,#0x3C+RefSetDelegate]
__text:000D9E16                 STR             R1, [SP,#0x3C+RefInit]
__text:000D9E18                 MOV             R0, (selRef_stringWithFormat_ - 0xD9E28) ; selRef_stringWithFormat_
__text:000D9E20                 LDR.W           R10, [R2] ; "alloc"
__text:000D9E24                 ADD             R0, PC ; selRef_stringWithFormat_
__text:000D9E26                 LDR.W          


; This loop will iterate over X.X.X.0 through X.X.X.255
IP_Iterations_Loop
; Create our X.X.X.i string using our counter value, save the value into R6
MOVW            R0, #0xAF8C
MOV             R1, R11
MOVT.W          R0, #0x45
STR.W           R8, [SP,#0x3C+refTopOfStack] ; Update the stack counter with the real counters value, this will also be the 3rd argument for the string formatter
ADD             R0, PC ; classRef_NSString
LDR             R0, [R0] ; _OBJC_CLASS_$_NSString
MOV             R2, (cfstr_D_4 - 0xD9E4A) ; "%@%d"
LDR             R3, [SP,#0x3C+Id]
ADD             R2, PC  ; "%@%d"
BLX             _objc_msgSend
MOV             R6, R0
; Create a TCPConnection object
MOV             R0, (classRef_TcpConnection - 0xD9E5C) ; classRef_TcpConnection
MOV             R1, R10
ADD             R0, PC ; classRef_TcpConnection
LDR             R0, [R0] ; _OBJC_CLASS_$_TcpConnection
BLX             _objc_msgSend
; Call TCPConnection.Init();
LDR             R1, [SP,#0x3C+RefInit]
BLX             _objc_msgSend
; Call TCPConnection.SetDelegate(*IPScanner);
; NOTE: This appears to be a register that allows IPScanner to handle callbacks from TCPConnection
LDR             R1, [SP,#0x3C+RefSetDelegate]
MOV             R2, R5 ; Set R5 equal to our current IPScanner object
MOV             R4, R0 ; Set R4 equal to our TCPConnection object (this method must return a different object and override R0)
BLX             _objc_msgSend
; Execute TCPConnection("OpenWithHost:port:SSLDesc:errorStr")( "X.X.X.i", "443" )
MOVS            R1, #3
MOVS            R0, #0
STR             R1, [SP,#0x3C+refTopOfStack] ; set SSLDesc
MOV             R2, R6 ; Put our calculated IP into R6, (Parameter 1)
STR             R0, [SP,#0x3C+var_38] ; set ErrorMessage
MOV             R0, R4 ; Set R0 = TCPConnection Object
LDR             R1, [SP,#0x3C+RefOpenWithHost] ; Load "openWithHost:port:SSLDesc:errorStr:" into R1
MOVW            R3, #0x1BB ; Passed in a parameter of "443"
BLX             _objc_msgSend
; *m_connections.AddObject(TCPConnection) - Add our TCPConnection to the m_connections array
LDR             R0, [SP,#0x3C+RefConnections]
MOV             R2, R4
LDR             R1, [SP,#0x3C+RefAddObject]
LDR             R0, [R5,R0]
BLX             _objc_msgSend
; TCPConnection.Release()
LDR             R1, [SP,#0x3C+RefRelease]
MOV             R0, R4
BLX             _objc_msgSend
; Increment the counter
ADD.W           R8, R8, #1
CMP.W           R8, #0x100 ; 256 (Full IP Range)
; If(counter != 256){
BNE             IP_Iterations_Loop

; }
; Cleanup
ADD             SP, SP, #0x24
POP.W           {R8,R10,R11}
POP             {R4-R7,PC}
; End of function -[IPScanner testAddresses:]


IPScanner - (void)TcpConnectionOpenedForInput:(id)
Attributes: bp-based frame
; void __cdecl __IPScanner TcpConnectionOpenedForInput__(struct IPScanner *self, SEL, TcpConnectionId)
__IPScanner_TcpConnectionOpenedForInput__

; Local variables
__text:000DA2F8 var_48          = -0x48
__text:000DA2F8 var_44          = -0x44
__text:000DA2F8 var_40          = -0x40
__text:000DA2F8 valPort         = -0x3C
__text:000DA2F8 refObjectAtIndex= -0x38
__text:000DA2F8 refAddress      = -0x34
__text:000DA2F8 refIsEqualTostring= -0x30
__text:000DA2F8 refSetHasRemote = -0x2C
__text:000DA2F8 var_28          = -0x28
__text:000DA2F8 refCountOrAlloc        = -0x24
__text:000DA2F8 refHost         = -0x20
; Parameters
__text:000DA2F8 TcpConnectionId              = -0x1C
; Typical Init shit, put TcpConnectionId into R6, put self reference into R8
__text:000DA2F8                 PUSH            {R4-R7,LR}
__text:000DA2FA                 ADD             R7, SP, #0xC
__text:000DA2FC                 PUSH.W          {R8,R10,R11}
__text:000DA300                 SUB             SP, SP, #0x30
__text:000DA302                 MOV             R6, R2
__text:000DA304                 MOV             R8, R0
__text:000DA306                 STR             R6, [SP,#0x48+TcpConnectionId]
; Retrieve the host from the TCPConnection, put it into R5
__text:000DA308                 MOV             R0, (selRef_host - 0xDA314) ; selRef_host
__text:000DA310                 ADD             R0, PC ; selRef_host
__text:000DA312                 LDR             R1, [R0] ; "host"
__text:000DA314                 MOV             R0, R6
__text:000DA316                 STR             R1, [SP,#0x48+refHost]
__text:000DA318                 BLX             _objc_msgSend
__text:000DA31C                 MOV             R5, R0
; Retrieve the port from the TCPConnection, put it into R2
__text:000DA31E                 MOV             R0, (selRef_port - 0xDA32A) ; selRef_port
__text:000DA326                 ADD             R0, PC ; selRef_port
__text:000DA328                 LDR             R4, [R0] ; "port"
__text:000DA32A                 MOV             R0, R6
__text:000DA32C                 MOV             R1, R4
__text:000DA32E                 BLX             _objc_msgSend
__text:000DA332                 MOV             R2, R0
; Log some shit
__text:000DA334                 MOV             R0, (cfstr_Tcpconnectio_3 - 0xDA342) ; "TcpConnectionOpenedForInput ip:%@ port:%d"
__text:000DA33C                 MOV             R1, R5
__text:000DA33E                 ADD             R0, PC  ; "TcpConnectionOpenedForInput ip:%@ port:%d"
__text:000DA340                 MOV             R5, R8
__text:000DA342                 BLX             _NSLog
; Retrieve the port from the TCPConnection (again), put it into R10
__text:000DA346                 MOV             R0, R6
__text:000DA348                 MOV             R1, R4
__text:000DA34A                 BLX             _objc_msgSend
__text:000DA34E                 MOV             R10, R0
; Retrieve the port from the TCPConnection (again), store the value of the port into a local variable, 
__text:000DA350                 MOV             R0, R6
__text:000DA352                 MOV             R1, R4
__text:000DA354                 STR.W           R10, [SP,#0x48+valPort]
__text:000DA358                 BLX             _objc_msgSend
__text:000DA35C                 MOVW            R1, #0xAEA6
; Store the port in R4, retrieve the count of *m_successTCDs array
__text:000DA35C                 MOVW            R1, #0xAEA6
__text:000DA360                 MOV             R4, R0
__text:000DA362                 MOVT.W          R1, #0x4A
__text:000DA366                 MOVW            R0, #0x48E0
__text:000DA36A                 ADD             R1, PC  ; NSMutableArray *m_successTCDs;
__text:000DA36C                 MOVT.W          R0, #0x45
__text:000DA370                 ADD             R0, PC ; selRef_count
__text:000DA372                 LDR.W           R8, [R1] ; NSMutableArray *m_successTCDs;
__text:000DA376                 LDR             R1, [R0] ; "count"
__text:000DA378                 STR             R1, [SP,#0x48+refCountOrAlloc]
__text:000DA37A                 LDR.W           R0, [R5,R8]
__text:000DA37E                 BLX             _objc_msgSend
; If port is = 443, set R1 equal to 1 (this is a flag)
__text:000DA382                 MOVW            R1, #0x1BB
__text:000DA386                 CMP             R10, R1
__text:000DA388                 MOV.W           R1, #0
__text:000DA38C                 MOV.W           R2, #0
__text:000DA390                 IT EQ
__text:000DA392                 MOVEQ           R1, #1
; Store our flag, if the port is 0x7A6B (31339) set R2 equal to 1 (this is a flag)
__text:000DA394                 MOVW            R3, #0x7A6B
__text:000DA398                 STR             R1, [SP,#0x48+FlagIsSSL]
__text:000DA39A                 CMP             R4, R3
__text:000DA39C                 IT EQ
__text:000DA39E                 MOVEQ           R2, #1
; Store our flag, check if the count of *m_successTCDS is 0, branch if it is zero
__text:000DA3A0                 CMP             R0, #0
__text:000DA3A2                 STR             R2, [SP,#0x48+FlagIsPort31339]
__text:000DA3A4                 BEQ
; if(count(*m_successTCDs) != 0){
; CODE IGNORED - Simply checks if the array already has this HOST, if it does, updates the HasRemote() using the 31339 port flag (if 31339 port, HasRemote=true)
; }
loc_DA43C
; Allocate space for an IPScannerInfo object
; Store "alloc" into "refCountOrAlloc"
MOV             R1, (selRef_alloc - 0xDA450) ; selRef_alloc
MOV             R0, (classRef_IPScannerInfo - 0xDA452) ; classRef_IPScannerInfo
ADD             R1, PC ; selRef_alloc
ADD             R0, PC ; classRef_IPScannerInfo
LDR             R1, [R1] ; "alloc"
LDR             R0, [R0] ; _OBJC_CLASS_$_IPScannerInfo
STR             R1, [SP,#0x48+refCountOrAlloc]
BLX             _objc_msgSend
; Intialize the IPScannerInfo object
MOV             R1, (selRef_init - 0xDA466) ; selRef_init
ADD             R1, PC ; selRef_init
LDR.W           R10, [R1] ; "init"
MOV             R1, R10
BLX             _objc_msgSend
; Save IPScannerInfo in R4, retrieve the Host from TCPConnection & store it in R2
LDR             R6, [SP,#0x48+TcpConnectionId]
MOV             R4, R0
LDR             R1, [SP,#0x48+refHost]
MOV             R0, R6
BLX             _objc_msgSend
MOV             R2, R0
; Call IPScannerInfo."setAddress:"(TCPConnection."Host")
MOV             R0, (selRef_setAddress_ - 0xDA488) ; selRef_setAddress_
ADD             R0, PC ; selRef_setAddress_
LDR             R1, [R0] ; "setAddress:"
MOV             R0, R4
BLX             _objc_msgSend
; Call IPScannerInfo."setHasVideos:"(FlagIsSSL)
MOV             R0, (selRef_setHasVideos_ - 0xDA49C) ; selRef_setHasVideos_
LDR             R2, [SP,#0x48+FlagIsSSL]
ADD             R0, PC ; selRef_setHasVideos_
LDR             R1, [R0] ; "setHasVideos:"
MOV             R0, R4
BLX             _objc_msgSend
; Call IPScannerInfo."setLastConnection:"(*TCPConnection)
MOVW            R0, #0x7A20
MOV             R2, R6
MOVT.W          R0, #0x45
ADD             R0, PC ; selRef_setLastConnection_
LDR             R1, [R0] ; "setLastConnection:"
MOV             R0, R4
BLX             _objc_msgSend
; Check if port is 443, branch if it is not
LDR             R0, [SP,#0x48+valPort]
MOVW            R1, #0x1BB
CMP             R0, R1
BNE             loc_DA560
; if(Port == 443){
; Call *m_successTCDs."addObject:"(*IPScannerInfo)
MOVW            R0, #0x4716
MOV             R2, R4
MOVT.W          R0, #0x45
ADD             R0, PC ; selRef_addObject_
LDR.W           R11, [R0] ; "addObject:"
LDR.W           R0, [R5,R8]
MOV             R1, R11
BLX             _objc_msgSend
; Create a TcpConnection object - Call _OBJC_CLASS_$_TcpConnection."alloc"()
MOV             R0, (classRef_TcpConnection - 0xDA4E8) ; classRef_TcpConnection
LDR             R1, [SP,#0x48+refCountOrAlloc]
ADD             R0, PC ; classRef_TcpConnection
LDR             R0, [R0] ; _OBJC_CLASS_$_TcpConnection
BLX             _objc_msgSend
; Call TcpConnection."init"(), save the TcpConnection instance in R6
MOV             R1, R10
BLX             _objc_msgSend
MOV             R6, R0
; Set the delegate of the TcpConnection to be the IPScanner (self)
MOV             R0, (selRef_setDelegate_ - 0xDA502) ; selRef_setDelegate_
MOV             R2, R5
ADD             R0, PC ; selRef_setDelegate_
LDR             R1, [R0] ; "setDelegate:"
MOV             R0, R6
BLX             _objc_msgSend
; Get IPScannerInfo."address:" and store it in R2
MOV             R0, (selRef_address - 0xDA514) ; selRef_address
ADD             R0, PC ; selRef_address
LDR             R1, [R0] ; "address"
MOV             R0, R4
BLX             _objc_msgSend
MOV             R2, R0
; Since we found a port 443 match, try to find a port 31339 match.
; Call TcpConnection."selRef_openWithHost_port_SSLDesc_errorStr_"(IPScannerInfo.Address, 31339)
MOV             R0, (selRef_openWithHost_port_SSLDesc_errorStr_ - 0xDA52C) ; selRef_openWithHost_port_SSLDesc_errorStr_
MOVW            R3, #0x7A6B ; 31339
ADD             R0, PC ; selRef_openWithHost_port_SSLDesc_errorStr_
LDR             R1, [R0] ; "openWithHost:port:SSLDesc:errorStr:"
MOVS            R0, #0
STR             R0, [SP,#0x48+var_48]
STR             R0, [SP,#0x48+var_44]
MOV             R0, R6
BLX             _objc_msgSend
; Add the new connection to our connections list
; Call *m_connections."addObject:"(*TcpConnection)
MOVW            R0, #0xACC8
MOV             R1, R11
MOVT.W          R0, #0x4A
MOV             R2, R6
ADD             R0, PC  ; NSMutableArray *m_connections;
LDR             R0, [R0] ; NSMutableArray *m_connections;
LDR             R0, [R5,R0]
BLX             _objc_msgSend
; Call TcpConnection.Release()
MOV             R0, (selRef_release - 0xDA55A) ; selRef_release
ADD             R0, PC ; selRef_release
LDR             R1, [R0] ; "release"
MOV             R0, R6
BLX             _objc_msgSend
; }
; Release IPScannerInfo object, normal cleanup
loc_DA560
MOV             R0, (selRef_release - 0xDA56C) ; selRef_release
ADD             R0, PC ; selRef_release
LDR             R1, [R0] ; "release"
MOV             R0, R4
ADD             SP, SP, #0x30
POP.W           {R8,R10,R11}
POP.W           {R4-R7,LR}
B.W             j__objc_msgSend






; NOTE: NetworkManager.ScanningTimeout() calls IPScanner.EndScan()



; The jist of this function is that it will take *m_successTCDs items and determine if they have minds, are transcoders, etc based on their TSN (SSL Cert Description)
; If an item in *m_successTCDS is a transcoder, it will be removed from the array and added to *m_successTranscoders/
; No matter what happens, at the end all objects will be removed from *m_connections;

IPScanner - (void)endScan
Attributes: bp-based frame

void __cdecl __IPScanner endScan_(struct IPScanner *self, SEL)
__IPScanner_endScan_                    ; DATA XREF: __objc_const:004DD6F8 o

; Internal attributes
__text:000D9FF0 refSelf         = -0x78
__text:000D9FF0 valTSNPart2          = -0x74
__text:000D9FF0 valTSNPart3          = -0x70
__text:000D9FF0 strLastConnection= -0x6C
__text:000D9FF0 strServerCertDescription= -0x68
__text:000D9FF0 strComponentsSeparatedByString= -0x64
__text:000D9FF0 strStringWithFormat= -0x60
__text:000D9FF0 strHardwareTypeFromBodyID= -0x5C
__text:000D9FF0 refSuccessTranscoders= -0x58
__text:000D9FF0 strAddObject    = -0x54
__text:000D9FF0 strRemoveObject = -0x50
__text:000D9FF0 strSetLastConnection= -0x4C
__text:000D9FF0 strDump         = -0x48
__text:000D9FF0 strSetHasMind   = -0x44
__text:000D9FF0 strAddress      = -0x40
__text:000D9FF0 refSuccessTCDs  = -0x3C
__text:000D9FF0 StrCount        = -0x38
__text:000D9FF0 refNSStringInstance= -0x34
__text:000D9FF0 refNSStringClass= -0x30
__text:000D9FF0 valIncrementerCount= -0x2C
__text:000D9FF0 strObjectAtIndex= -0x28
__text:000D9FF0 strSetTSN       = -0x24
__text:000D9FF0 strLength       = -0x20
; First Parameter ?
; NOTE: This doesn't make much sense
__text:000D9FF0 strTSN          = -0x1C

; Typical init, store self reference in R10

__text:000D9FF0                 PUSH            {R4-R7,LR}
__text:000D9FF2                 ADD             R7, SP, #0xC
__text:000D9FF4                 PUSH.W          {R8,R10,R11}
__text:000D9FF8                 SUB             SP, SP, #0x60
__text:000D9FFA                 MOV             R10, R0
; Log
__text:000D9FFC                 MOV             R0, (cfstr_IpScannerEndSc - 0xDA008) ; "IP SCANNER: end scan"
__text:000DA004                 ADD             R0, PC  ; "IP SCANNER: end scan"
__text:000DA006                 BLX             _NSLog
; Get the count of items in *m_successTCDS
__text:000DA00A                 MOV             R1, (_OBJC_IVAR_$_IPScanner.m_successTCDs - 0xDA01A) ; NSMutableArray *m_successTCDs;
__text:000DA012                 MOVW            R0, #0x4C34
__text:000DA016                 ADD             R1, PC  ; NSMutableArray *m_successTCDs;
__text:000DA018                 MOVT.W          R0, #0x45
__text:000DA01C                 ADD             R0, PC ; selRef_count
__text:000DA01E                 LDR             R6, [R1] ; NSMutableArray *m_successTCDs;
__text:000DA020                 LDR             R1, [R0] ; "count"
__text:000DA022                 STR             R6, [SP,#0x78+refSuccessTCDs]
__text:000DA024                 LDR.W           R0, [R10,R6]
__text:000DA028                 STR             R1, [SP,#0x78+strCount]
__text:000DA02A                 BLX             _objc_msgSend
; Store the count-1 (last index) of *m_successTCDS in R2 (this will be used as the incrementer later)
; If there is not at least 1 item in *m_successTCDS, branch
__text:000DA02E                 SUBS            R2, R0, #1
__text:000DA030                 CMP             R2, #0
__text:000DA032                 BLT.W           loc_DA2AA

; if(count(*m_successTCDS) > 0){
; Initialize properties before looping
; init_before_loop
MOV             R3, (selRef_dump - 0xDA062) ; selRef_dump
MOV             R0, (selRef_setHasMind_ - 0xDA05A) ; selRef_setHasMind_
MOV             R9, (selRef_removeObject_ - 0xDA07A) ; selRef_removeObject_
MOV             R5, (selRef_address - 0xDA060) ; selRef_address
ADD             R0, PC ; selRef_setHasMind_
MOVW            R1, #0x4B6E
ADD             R5, PC ; selRef_address
ADD             R3, PC ; selRef_dump
MOVT.W          R1, #0x45
MOVW            R4, #0x7E52
LDR             R0, [R0] ; "setHasMind:"
MOVT.W          R4, #0x45
LDR             R5, [R5] ; "address"
STR             R0, [SP,#0x78+strSetHasMind]
ADD             R1, PC ; selRef_addObject_
LDR             R0, [R3] ; "dump"
ADD             R9, PC ; selRef_removeObject_
STR             R5, [SP,#0x78+strAddress]
ADD             R4, PC ; selRef_setLastConnection_
STR             R0, [SP,#0x78+strDump]
MOV             R0, (_OBJC_IVAR_$_IPScanner.m_successTranscoders - 0xDA08C) ; NSMutableArray *m_successTranscoders;
LDR             R3, [R4] ; "setLastConnection:"
ADD             R0, PC  ; NSMutableArray *m_successTranscoders;
LDR.W           R11, [R9] ; "removeObject:"
LDR             R1, [R1] ; "addObject:"
LDR             R0, [R0] ; NSMutableArray *m_successTranscoders;
STR             R3, [SP,#0x78+strSetLastConnection]
STR.W           R11, [SP,#0x78+strRemoveObject]
STR             R1, [SP,#0x78+strAddObject]
STR             R0, [SP,#0x78+refSuccessTranscoders]
MOV             R0, (selRef_hardwareTypeFromBodyID_tsnIndex_ - 0xDA0A8) ; selRef_hardwareTypeFromBodyID_tsnIndex_
ADD             R0, PC ; selRef_hardwareTypeFromBodyID_tsnIndex_
LDR             R0, [R0] ; "hardwareTypeFromBodyID:tsnIndex:"
STR             R0, [SP,#0x78+strHardwareTypeFromBodyID]
MOV             R0, (selRef_stringWithFormat_ - 0xDA0B6) ; selRef_stringWithFormat_
ADD             R0, PC ; selRef_stringWithFormat_
LDR             R0, [R0] ; "stringWithFormat:"
STR             R0, [SP,#0x78+strStringWithFormat]
MOV             R0, (selRef_length - 0xDA0C4) ; selRef_length
ADD             R0, PC ; selRef_length
LDR             R0, [R0] ; "length"
STR             R0, [SP,#0x78+strLength]
MOV             R0, (selRef_componentsSeparatedByString_ - 0xDA0D2) ; selRef_componentsSeparatedByString_
ADD             R0, PC ; selRef_componentsSeparatedByString_
LDR             R0, [R0] ; "componentsSeparatedByString:"
STR             R0, [SP,#0x78+strComponentsSeparatedByString]
MOV             R0, (selRef_tsn - 0xDA0E0) ; selRef_tsn
ADD             R0, PC ; selRef_tsn
LDR             R0, [R0] ; "tsn"
STR             R0, [SP,#0x78+strTSN]
MOV             R0, (selRef_setTsn_ - 0xDA0EE) ; selRef_setTsn_
ADD             R0, PC ; selRef_setTsn_
LDR             R0, [R0] ; "setTsn:"
STR             R0, [SP,#0x78+strSetTSN]
MOV             R0, (selRef_serverCertDescription - 0xDA0FC) ; selRef_serverCertDescription
ADD             R0, PC ; selRef_serverCertDescription
LDR             R0, [R0] ; "serverCertDescription"
STR             R0, [SP,#0x78+strServerCertDescription]
MOV             R0, (selRef_lastConnection - 0xDA10A) ; selRef_lastConnection
ADD             R0, PC ; selRef_lastConnection
LDR             R0, [R0] ; "lastConnection"
STR             R0, [SP,#0x78+strLastConnection]
MOV             R0, (selRef_objectAtIndex_ - 0xDA118) ; selRef_objectAtIndex_
ADD             R0, PC ; selRef_objectAtIndex_
LDR             R0, [R0] ; "objectAtIndex:"
STR             R0, [SP,#0x78+strObjectAtIndex]
; TODO
beginning_of_loop
; Call m_successTCDs."ObjectAtIndex"(i), updated incrementer in memory
__text:000DA11A                 LDR.W           R0, [R10,R6]
__text:000DA11E                 LDR             R1, [SP,#0x78+strObjectAtIndex]
__text:000DA120                 STR             R2, [SP,#0x78+valIncrementerCount]
__text:000DA122                 BLX             _objc_msgSend
; Set the retrieved *IPScannerInfo reference into R5
; Retrieve the last *TCPConnection from the *IPScannerInfo
__text:000DA126                 LDR             R1, [SP,#0x78+strLastConnection]
__text:000DA128                 MOV             R5, R0
__text:000DA12A                 BLX             _objc_msgSend
; Call *TCPConnection."ServerCertDescription"(), store value in R2
__text:000DA12E                 LDR             R1, [SP,#0x78+strServerCertDescription]
__text:000DA130                 BLX             _objc_msgSend
; Call *IPScannerInfo."SetTSN"(*ServerCertDescription)
; TODO - This is very important
__text:000DA134                 LDR             R1, [SP,#0x78+strSetTSN]
__text:000DA136                 MOV             R2, R0
__text:000DA138                 MOV             R0, R5
__text:000DA13A                 BLX             _objc_msgSend
; Call *IPScannerInfo."TSN"(), store the result in R1
__text:000DA13E                 LDR             R4, [SP,#0x78+strTSN]
__text:000DA140                 MOV             R0, R5
__text:000DA142                 MOV             R1, R4
__text:000DA144                 BLX             _objc_msgSend
__text:000DA148                 MOV             R1, R0
; Log
__text:000DA14A                 MOV             R0, (cfstr_IpscannerCertD - 0xDA156) ; "IPScanner:Cert Description:%@"
__text:000DA152                 ADD             R0, PC  ; "IPScanner:Cert Description:%@"
__text:000DA154                 BLX             _NSLog
; Call *IPScannerInfo."TSN"()
__text:000DA158                 MOV             R0, R5
__text:000DA15A                 MOV             R1, R4
__text:000DA15C                 BLX             _objc_msgSend
; Call *TSN."ComponentsSeparatedByString"("-"), store result in R8
__text:000DA160                 LDR             R1, [SP,#0x78+strComponentsSeparatedByString]
__text:000DA162                 MOV             R2, (stru_587698 - 0xDA16E) ; "-"
__text:000DA16A                 ADD             R2, PC  ; "-"
__text:000DA16C                 BLX             _objc_msgSend
__text:000DA170                 MOV             R8, R0
; Call *IPScannerInfo."TSN"()
__text:000DA172                 MOV             R0, R5
__text:000DA174                 MOV             R1, R4
__text:000DA176                 BLX             _objc_msgSend
; Call *IPScannerInfo."Length"(), branch if it is not equal to 18...
__text:000DA17A                 LDR             R1, [SP,#0x78+strLength]
__text:000DA17C                 BLX             _objc_msgSend
__text:000DA180                 CMP             R0, #0x12
BNE             TSN_String_Invalid
; if(*IPScannerInfo."Length"() != 18){
; See if the count of R8 (TSN seperated by "-") is equal to 4, branch if it is not
LDR             R1, [SP,#0x78+strCount]
MOV             R0, R8
BLX             _objc_msgSend
CMP             R0, #4
BNE             TSN_String_Invalid
; NOTE: We branch here to the ELSE statement further below!
; Get the index [0] of the TSN split by "-", save it into valTSNPart1
; We also save an instance of the stringClass
MOVW            R0, #0xAC26
MOVS            R2, #0
MOVT.W          R0, #0x45
LDR.W           R11, [SP,#0x78+strObjectAtIndex]
ADD             R0, PC ; classRef_NSString
LDR             R0, [R0] ; _OBJC_CLASS_$_NSString
MOV             R1, R11
STR             R0, [SP,#0x78+refNSStringClass]
MOV             R0, R8
BLX             _objc_msgSend
STR             R0, [SP,#0x78+valTSNPart1]
; Get the index [1] of the TSN split by "-" (R8), save it into R10
; We also save R10 into R4 beforehand
MOV             R0, R8
MOV             R1, R11
MOVS            R2, #1
BLX             _objc_msgSend
MOV             R4, R10
MOV             R10, R0
; Get the index [2] of the TSN split by "-" (R8), save it into R6
MOV             R0, R8
MOV             R1, R11
MOVS            R2, #2
BLX             _objc_msgSend
MOV             R6, R0
; Get the index [3] of the TSN split by "-" (R8)
MOV             R0, R8
MOV             R1, R11
MOVS            R2, #3
BLX             _objc_msgSend
; Save our TSN Parts to memory
STR.W           R10, [SP,#0x78+refSelf] ; Save Index [1]
MOV             R10, R4 ; Restore R10 to be "self"
STR             R6, [SP,#0x78+valTSNPart2] ; Save Index [2]
STR             R0, [SP,#0x78+valTSNPart3] ; Save Index [3]
; Call StringClass.StringWithFormat("%@%@%@%@",TSNPart1)
; TODO - This doesn't make sense, why are we ignoring the other TSN parts?
LDR             R0, [SP,#0x78+refNSStringClass] ;
LDR             R1, [SP,#0x78+strStringWithFormat]
MOV             R2, (stru_58E7C8 - 0xDA1EE) ; "%@%@%@%@"
LDR             R3, [SP,#0x78+valTSNPart1]
ADD             R2, PC  ; "%@%@%@%@"
LDR.W           R11, [SP,#0x78+strRemoveObject]
LDR             R6, [SP,#0x78+refSuccessTCDs]
BLX             _objc_msgSend
; Call *IPScannerInfo.SetTSN(StringClass.StringWithFormat("%@%@%@%@",TSNPart1))
LDR             R1, [SP,#0x78+strSetTSN]
MOV             R2, R0
MOV             R0, R5
BLX             _objc_msgSend
; Determine the hardware type from the body id
; NOTE: We branch here if the ServerCertDescription is not empty
Determine_Hardware_Type
; Call _OBJC_CLASS_$_NetworkManager.HardwareTypeFromBodyId(*IPScannerInfo.Tsn(),0)
MOV             R0, (classRef_NetworkManager - 0xDA20E) ; classRef_NetworkManager
LDR             R1, [SP,#0x78+strTSN]
ADD             R0, PC ; classRef_NetworkManager
LDR             R4, [R0] ; _OBJC_CLASS_$_NetworkManager
MOV             R0, R5
BLX             _objc_msgSend
LDR             R1, [SP,#0x78+strHardwareTypeFromBodyID]
MOV             R2, R0
MOV             R0, R4
MOVS            R3, #0
BLX             _objc_msgSend
; If the hardware type returned is NOT 5...branch 
CMP             R0, #5
BNE             loc_DA274
; if(HardwareType != 5){
__text:000DA274 Not_Transcoder_Hardware
; NOTE: R0 is our hardware type enum value (1-5)
; TODO - This logic is confusing, try to figure out what actually has a "mind", is it 2, 3, or 4? or a combo?
; If HardwareType is <= 3, branch (it does not have a mind!)
__text:000DA274                 SUBS            R1, R0, #1 ; Add 1 to our enum value, store it in R1
__text:000DA276                 CMP             R1, #2 ; Subtract (HardwareType-1) from 2, set the carry bit if (HardwareType-1) > 2
BCC             loc_DA28C ; Branch if Carry is clear (we did not go negative)
; If HardwareType != 4, branch (it does not have a mind)
__text:000DA27A                 CMP             R0, #3
__text:000DA27C                 IT NE
__text:000DA27E                 CMPNE           R0, #4
__text:000DA280         BEQ             loc_DA28C
; If we got here, HardwareType is 4
; Call *IPScannerInfo.SetHasMind(1)
LDR             R1, [SP,#0x78+strSetHasMind]
MOV             R0, R5
MOVS            R2, #1
loc_DA288
BLX             _objc_msgSend
loc_DA28C
; Call *IPScannerInfo.SetLastConnection(null)
LDR             R1, [SP,#0x78+strSetLastConnection]
MOV             R0, R5
MOVS            R2, #0
BLX             _objc_msgSend
; Call *IPScannerInfo.Dump()
; TODO - What does dump do? Delete it?
LDR             R1, [SP,#0x78+strDump]
MOV             R0, R5
BLX             _objc_msgSend
B End_of_loop
; } else {
Transcoder_Hardware
; Call *m_successfulTranscoders.AddObject(*IPScannerInfo)
LDR             R0, [SP,#0x78+refSuccessTranscoders]
MOV             R2, R5
LDR             R1, [SP,#0x78+strAddObject]
LDR.W           R0, [R10,R0]
BLX             _objc_msgSend
; Remove from *m_successTCDs
LDR.W           R0, [R10,R6]
MOV             R1, R11 ; RemoveObject
MOV             R2, R5 ; *IPScannerInfo
B               loc_DA288
; }
; } else if (*IPScannerInfo."Length"() != 18 || *TSN."ComponentsSeparatedByString"("-").Length() != 4){
TSN_String_Invalid
; Call *IPScannerInfo.TSN().Length(), check if it is equal to 0, branch if it is (0)
LDR             R1, [SP,#0x78+strTSN]
MOV             R0, R5
BLX             _objc_msgSend
LDR             R1, [SP,#0x78+strLength]
BLX             _objc_msgSend
CMP             R0, #0xF
BEQ             Determine_Hardware_Type
; if(*IPScannerInfo.TSN().Length() != 0){
; BRANCH TO "Determine Hardware Type"
; }else{
; Cleanup, this is not a tivo!
Cleanup_Invalid_IPScannerInfo
; Retrieve the address for this IPScannerInfo
LDR             R1, [SP,#0x78+strAddress]
MOV             R0, R5
BLX             _objc_msgSend
MOV             R1, R0
; Log
MOV             R0, (cfstr_Removing - 0xDA264) ; "Removing %@"
ADD             R0, PC  ; "Removing %@"
BLX             _NSLog
; Call m_successTCDs.removeObject(*IPScannerInfo)
LDR.W           R0, [R10,R6]
MOV             R1, R11
MOV             R2, R5
BLX             _objc_msgSend
B               End_of_loop
; }
; }
; Increment the counter, if it is not 0, continue looping
End_of_loop
LDR             R2, [SP,#0x78+valIncrementerCount]
SUBS            R2, #1
CMP.W           R2, #0xFFFFFFFF
BGT.W           beginning_of_loop

; }
; Erase all items from the *m_connections array, normal cleanup

__text:000DA2AA loc_DA2AA
__text:000DA2AA                 MOV             R0, (_OBJC_IVAR_$_IPScanner.m_connections - 0xDA2BA) ; NSMutableArray *m_connections;
__text:000DA2B2                 MOVW            R1, #0x4A2C
__text:000DA2B6                 ADD             R0, PC  ; NSMutableArray *m_connections;
__text:000DA2B8                 MOVT.W          R1, #0x45
__text:000DA2BC                 ADD             R1, PC ; selRef_removeAllObjects
__text:000DA2BE                 LDR             R0, [R0] ; NSMutableArray *m_connections;
__text:000DA2C0                 LDR             R1, [R1] ; "removeAllObjects"
__text:000DA2C2                 LDR.W           R0, [R10,R0]
__text:000DA2C6                 ADD             SP, SP, #0x60
__text:000DA2C8                 POP.W           {R8,R10,R11}
__text:000DA2CC                 POP.W           {R4-R7,LR}
__text:000DA2D0                 B.W             j__objc_msgSend
__text:000DA2D0 ; End of function -[IPScan








; NOTE: NetworkManager."hardwareTypeFromBodyID:tsnIndex"() returns an enum based on the TCD value (before the first "-") that determines what type of box it is (transcoder vs others vs minds)

NetworkManager."hardwareTypeFromBodyID:tsnIndex"([String] (Server Certificate CN).Split('-')[0]) {

HardwareType Enum: {
0: NOT_A_TIVO
1: ??  - Guess: TIVO SD?
2: TIVO_HD
3: S3  - Guess : Tivo Series 3? TODO
4: Premiere - Guess : TIVO Premiere? TODO ; HAS MIND!
5: TRANSCODER_SUPPORT  - Guess : TIVO Stream;
}
Look up table
| TSN Value  | Enum |
-----------------------
1   1
2   1
3   1
4   1
5   1
627   1
640   1
649   1
653   1
648   2
652   2
658   2
663   2
6E8   2
6F2   2
6F8   2
A94   5
AD4   5
AE4   5
AF0   3
A90   3
A92   4
AE2   4
other   0
-----------------------
}





No comments:

Post a Comment