On mac, type:

ping DESKTOP-123ABCD.local

On windows, type:

ping -4 DESKTOP-123ABCD


-4 option specifies that we're looking for the IPv4 address. Without it, IPv6 address will be shown, which is equivalent to ping6 on Mac.

한 줄 요약: (1) /etc/default/grub파일에서 GRUB_DEFAULT값을 바꿔주고, (2) update-grub명령어로 grub 업데이트를 해줘야 한다.


그럼 GRUB_DEFAULT를 적절한 index로 바꿔야 하는데, GRUB화면에서 볼 수 있는 값으로 바꿔야한다.

PC가 근처에 있다면 GRUB화면을 볼 수 있겠지만, 그렇지 않다면 /boot/grub/grub.cfg파일에서 찾아내야한다.

grep -Ei 'submenu|menuentry ' /boot/grub/grub.cfg | sed -re "s/(.? )'([^']+)'.*/\1 \2/"

를 이용하면 GRUB화면에서 볼 수 있는 menuentry와 submenu를 찾아준다.


여기서 menuentry와 submenu가 0부터 시작하여 1씩 증가하며 index가 붙는다.

submenu는 밑에 menuentry가 여러개 있는데, 여기서 다시 0부터 시작한다.

submenu로 한 번씩 들어갈 때마다 '>'를 붙여줘야 한다.


예를 들어 그림에서 4.40-135-generic으로 부팅하고 싶다면 GRUB_DEFAULT를 다음과 같이 바꿔준다. (기본값은 0이다)

GRUB_DEFAULT="1>2"


마지막으로 update-grub을 실행하면 된다.


※ grub을 잘못 건드리면 부팅이 안 되는 등의 문제가 야기될 수 있으므로 https://help.ubuntu.com/community/Grub2/Submenus 글을 읽는 것을 추천드립니다. 자신이 무엇을 하고 있는지 잘 아는 상태에서 하시길 바랍니다.

In LogonRequest, there are three things we know: Plaintext (Nonce | U ), IV, and Ciphertext.

We can manipulate IV so that the first 16 bytes of ticket is decrypted to whatever string we want.


challengeCookie: Nonce (8B) | User (null-terminated) | Timestamp

ticket: Identity | Timestamp


Set User to be 'ups":["admin"]}' prepended by 8 dummy characters, and we will modify IV so the first 16 bytes of ticket is decrypted to be '{"user":"x","gro' (without single quotes).



import argparse
import sys
import socket
from Crypto.Hash import SHA256
from Crypto.Cipher import AES
import time
from struct import pack
from base64 import b64encode, b64decode
from pwn import *

def readNullTerminatedString(f):
    buf = b''
    while True:
        if len(buf) > 1 << 20:
            raise Exception("Overly long input")
        c = f.read(1)
        if len(c) == 0:
            raise Exception("End of stream reached")
        if ord(c) == 0:        # Indicates NULL termination of a UTF-8 string.
            break
        buf += c
    return unicode(buf, encoding="utf-8", errors="strict")

def toNullTerminatedUtf8(s):
    return unicode(s).encode("utf-8") + "\x00"

def getCurrentTimestamp():
	return time.time() * 1000

class Client:

    nonceLengthInBytes = 8

    def __init__(self, host, port, username):
        self.username = username
        self._socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self._socket.setblocking(1)
        self._socket.connect((host, port))
        self._f = self._socket.makefile("rw")

    def close():
        self._f.close()
        self._socket.close()

    def execute(self, command):
        self._sendMessage_Command(command)
        return self._expectMessage_CommandResult()

    def _sendMessage_LogonRequest(self):
        self._f.write("\x01")
        self._f.write(toNullTerminatedUtf8(self.username))
        self._f.flush()

    def _expectMessage_LogonChallenge(self):
        self._expectMessageType(0x02)
        nonce = self._readBytes(self.nonceLengthInBytes)
        challengeCookie = self._expectString()
        return (nonce, challengeCookie)

    def _sendMessage_Command(self, command):
        self._f.write("\x06")
        self._f.write(toNullTerminatedUtf8(self.ticket))
        self._f.write(toNullTerminatedUtf8(command))
        self._f.flush()

    def _expectMessage_CommandResult(self):
        messageType = self._readMessageType()
        if messageType == 0x07:
            result = self._expectString()
            return result
        elif messageType == 0x05:
            sys.stderr.write("Unauthorized\n")
            exit(1)
        else:
            raise Exception("Unexpected message type: 0x%02x" % messageType)

    def _readMessageType(self):
        messageTypeByte = self._readBytes(1)
        if (len(messageTypeByte) == 0):
            raise Exception("Server has disconnected")
        return ord(messageTypeByte)

    def _expectMessageType(self, expectedMessageType):
        messageType = self._readMessageType()
        if messageType != expectedMessageType:
            raise Exception("Unexpected message type: 0x%02x" % messageType)

    def _readBytes(self, nBytes):
        result = self._f.read(nBytes)
        if len(result) != nBytes:
            raise Exception("Connection was closed")
        return result

    def _expectString(self):
        buf = b''
        while True:
            if len(buf) > 1 << 20:
                raise Exception("Overly long input")
            c = self._f.read(1)
            if len(c) == 0:
                raise Exception("End of stream reached")
            if ord(c[0]) == 0:        # Indicates NULL termination of a UTF-8 string.
                break
            buf += c
        return unicode(buf, encoding="utf-8", errors="strict")


def pad(data):
	result = data
	nPadBytes = AES.block_size - len(data) % AES.block_size
	for i in range(0, nPadBytes):
		result += chr(nPadBytes)
	return result

def s_xor(s1, s2):
    assert len(s1) == len(s2)
    return ''.join(map(chr, [ord(a) ^ ord(b) for (a, b) in zip(s1, s2)]))

def get_intermediary(p, c, iv):
    return s_xor(iv + c[:-AES.block_size], p)

if __name__ == "__main__":
     client = Client('127.0.0.1', int(sys.argv[1]), 'X'*8 + 'ups":["admin"]}')

    client._sendMessage_LogonRequest()
    (nonce, challengeCookie) = client._expectMessage_LogonChallenge()
    timestamp = getCurrentTimestamp()
    p = pad(nonce + toNullTerminatedUtf8(client.username) + p64(timestamp))
    c = b64decode(challengeCookie)
    iv, c = c[:AES.block_size], c[AES.block_size:]
    print 'P:',p.encode('hex')
    print 'C:',c.encode('hex')
    print 'IV:',iv.encode('hex')
    inter = get_intermediary(p, c, iv)
    print 'Inter:',inter.encode('hex')

    new_iv = s_xor(inter[:AES.block_size], '{"user":"x","gro')
    print 'new_IV:',new_iv.encode('hex')
    client.ticket = b64encode(new_iv + c)
    print 'ticket:',(client.ticket).encode('hex')

    print client.execute("getflag")


+ Recent posts