Переменная меняет тип при передаче в аргументе? - PullRequest
0 голосов
/ 01 февраля 2020

Я исправляю инструмент, который работает по сетевому протоколу NTLM, у меня есть объект структуры, где я индексирую строку и передаю функции, внутри области действия переменной переменная изменяется от <type 'str'> до <type 'instance'> .

вызов функции:

# type(self.challengeMessage['challenge']) == <type 'str'>
self.ParseHTTPHash(self.challengeMessage['challenge'])

внутри функции:

def ParseHTTPHash(challenge):
    # type(challenge) == <type 'instance'>
    challenge.encode("hex") # causes exception due to being instance type and not string

объект challengeMessage:

class NTLMAuthChallenge(Structure):

    structure = (
        ('','"NTLMSSP\x00'),
        ('message_type','<L=2'),
        ('domain_len','<H-domain_name'),
        ('domain_max_len','<H-domain_name'),
        ('domain_offset','<L=40'),
        ('flags','<L=0'),
        ('challenge','8s'),
        ('reserved','8s=""'),
        ('TargetInfoFields_len','<H-TargetInfoFields'),
        ('TargetInfoFields_max_len','<H-TargetInfoFields'),
        ('TargetInfoFields_offset','<L'),
        ('VersionLen','_-Version','self.checkVersion(self["flags"])'), 
        ('Version',':'),
        ('domain_name',':'),
        ('TargetInfoFields',':'))

    @staticmethod
    def checkVersion(flags):
        if flags is not None:
           if flags & NTLMSSP_NEGOTIATE_VERSION == 0:
              return 0
        return 8

    def getData(self):
        if self['TargetInfoFields'] is not None and type(self['TargetInfoFields']) is not bytes:
            raw_av_fields = self['TargetInfoFields'].getData()
            self['TargetInfoFields'] = raw_av_fields
        return Structure.getData(self)

    def fromString(self,data):
        Structure.fromString(self,data)
        self['domain_name'] = data[self['domain_offset']:][:self['domain_len']]
        self['TargetInfoFields'] = data[self['TargetInfoFields_offset']:][:self['TargetInfoFields_len']]
        return self

странная вещь, если я передаю self в ParseHTTPHasH(self) и ссылку на него внутри функции self.challengeMessage['challenge'], она не меняет тип на экземпляр. Что здесь происходит?

(Edit:)

Приносит извинения за неопределенность исходного сообщения, его трудно показать контекст с этим большим файлом

Общий контекст макета:

class HTTPRelayServer(Thread):
        ...
        # Parse NTLMv1/v2 hash with challengeMessage & token * custom *
        # check out responder ParseSMBHash to implement for smbrelayserver.py
        # replace impacket/impacket/examples/ntlmrelayx/servers/httprelayserver.py
        def ParseHTTPHash(self,client,data):
            LMhashLen    = struct.unpack('<H',data[12:14])[0]
            LMhashOffset = struct.unpack('<H',data[16:18])[0]
            LMHash       = data[LMhashOffset:LMhashOffset+LMhashLen].encode("hex").upper()

            NthashLen    = struct.unpack('<H',data[20:22])[0]
            NthashOffset = struct.unpack('<H',data[24:26])[0]
            NTHash       = data[NthashOffset:NthashOffset+NthashLen].encode("hex").upper()

            UserLen      = struct.unpack('<H',data[36:38])[0]
            UserOffset   = struct.unpack('<H',data[40:42])[0]
            User         = data[UserOffset:UserOffset+UserLen].replace('\x00','')

            # parameter reference
*---------> NumChal = self.challengeMessage['challenge'].encode("hex")

            if NthashLen == 24:
                HostNameLen     = struct.unpack('<H',data[46:48])[0]
                HostNameOffset  = struct.unpack('<H',data[48:50])[0]
                HostName        = data[HostNameOffset:HostNameOffset+HostNameLen].replace('\x00','')
                WriteHash       = '%s::%s:%s:%s:%s' % (User, HostName, LMHash, NTHash, NumChal)

            if NthashLen > 24:
                NthashLen      = 64
                DomainLen      = struct.unpack('<H',data[28:30])[0]
                DomainOffset   = struct.unpack('<H',data[32:34])[0]
                Domain         = data[DomainOffset:DomainOffset+DomainLen].replace('\x00','')
                HostNameLen    = struct.unpack('<H',data[44:46])[0]
                HostNameOffset = struct.unpack('<H',data[48:50])[0]
                HostName       = data[HostNameOffset:HostNameOffset+HostNameLen].replace('\x00','')
                WriteHash      = '%s::%s:%s:%s:%s' % (User, Domain, NumChal, NTHash[:32], NTHash[32:])
            return WriteHash

        def do_PROPFIND(self):
            proxy = False
            if (".jpg" in self.path) or (".JPG" in self.path):
                content = """<?xml version="1.0"?><D:multistatus xmlns:D="DAV:"><D:response><D:href>http://webdavrelay/file/image.JPG/</D:href><D:propstat><D:prop><D:creationdate>2016-11-12T22:00:22Z</D:creationdate><D:displayname>image.JPG</D:displayname><D:getcontentlength>4456</D:getcontentlength><D:getcontenttype>image/jpeg</D:getcontenttype><D:getetag>4ebabfcee4364434dacb043986abfffe</D:getetag><D:getlastmodified>Mon, 20 Mar 2017 00:00:22 GMT</D:getlastmodified><D:resourcetype></D:resourcetype><D:supportedlock></D:supportedlock><D:ishidden>0</D:ishidden></D:prop><D:status>HTTP/1.1 200 OK</D:status></D:propstat></D:response></D:multistatus>"""
            else:
                content = """<?xml version="1.0"?><D:multistatus xmlns:D="DAV:"><D:response><D:href>http://webdavrelay/file/</D:href><D:propstat><D:prop><D:creationdate>2016-11-12T22:00:22Z</D:creationdate><D:displayname>a</D:displayname><D:getcontentlength></D:getcontentlength><D:getcontenttype></D:getcontenttype><D:getetag></D:getetag><D:getlastmodified>Mon, 20 Mar 2017 00:00:22 GMT</D:getlastmodified><D:resourcetype><D:collection></D:collection></D:resourcetype><D:supportedlock></D:supportedlock><D:ishidden>0</D:ishidden></D:prop><D:status>HTTP/1.1 200 OK</D:status></D:propstat></D:response></D:multistatus>"""

            messageType = 0
            if self.headers.getheader('Authorization') is None:
                self.do_AUTHHEAD(message='NTLM')
                pass
            else:
                typeX = self.headers.getheader('Authorization')
                try:
                    _, blob = typeX.split('NTLM')
                    token = base64.b64decode(blob.strip())
                except:
                    self.do_AUTHHEAD()
                messageType = struct.unpack('<L', token[len('NTLMSSP\x00'):len('NTLMSSP\x00') + 4])[0]

            if messageType == 1:
                if not self.do_ntlm_negotiate(token, proxy=proxy):
                    LOG.info("do negotiate failed, sending redirect")
                    self.do_REDIRECT()
            elif messageType == 3:
                authenticateMessage = ntlm.NTLMAuthChallengeResponse()
                authenticateMessage.fromString(token)
                if authenticateMessage['flags'] & ntlm.NTLMSSP_NEGOTIATE_UNICODE:
                    LOG.info("Authenticating against %s://%s as %s\\%s SUCCEED" % (
                        self.target.scheme, self.target.netloc, authenticateMessage['domain_name'].decode('utf-16le'),
                        authenticateMessage['user_name'].decode('utf-16le')))
                else:
                    LOG.info("Authenticating against %s://%s as %s\\%s SUCCEED" % (
                        self.target.scheme, self.target.netloc, authenticateMessage['domain_name'].decode('ascii'),
                        authenticateMessage['user_name'].decode('ascii')))
                self.do_ntlm_auth(token, authenticateMessage)
                self.do_attack()

                # Function call
*------------>  print(self.ParseHTTPHash(self,str(token)))

                self.send_response(207, "Multi-Status")
                self.send_header('Content-Type', 'application/xml')
                self.send_header('Content-Length', str(len(content)))
                self.end_headers()
                self.wfile.write(content)
                return
        ...

Ответы [ 3 ]

0 голосов
/ 01 февраля 2020

Я думаю, ParseHTTPHa sh - это метод внутри вашего класса. Если это так, пожалуйста, передайте self в качестве первого параметра.

 def ParseHTTPHash(self,challenge)
0 голосов
/ 01 февраля 2020

Все обычные методы экземпляра класса (не @staticmethod или чего-либо другого) принимают первый параметр, который является объектом, для которого они были вызваны.

Итак, когда вы вызываете

obj.foo(param)

для объекта obj класса C, это примерно равно

C.foo(obj, param)

, которое обычно реализуется как

class C:
    def foo(self, param):
        pass # whatever

В противном случае метод экземпляра не будет не знаю, с каким экземпляром класса C он должен был работать.

Итак, если ParseHTTPHash является методом экземпляра, вы должны назвать его как self.ParseHTTPHash(param), но вы объявили это неправильно.

Если ParseHTTPHash является , а не методом экземпляра, вы должны не вызывать его как self.ParseHTTPHash(param), в первую очередь, потому что этот синтаксис специально для методов экземпляра.

Единственный способ узнать, какой случай применим, - это показать определение ParseHTTPHash в виде запроса @RafalS.

0 голосов
/ 01 февраля 2020
def ParseHTTPHash(challenge):

Если это бесплатная функция (определенная вне класса), вы не должны вызывать ее self.ParseHTTPHash(value), а просто ParseHTTPHash(value). Если это не @staticmethod и он внутри класса - добавьте self в качестве первого параметра.

...