您好,本站仅作演示所用,请勿下单付款!
商品分类

eBPF[13]:内核抓包核心原理

核心原理,就是对一些ssl的基础库进行hook. 原理几乎和r0capture 简直一模一样.

SSL/TLS plaintext capture, support openssl\libressl\boringssl\gnutls\nspr(nss) libraries.
GoTLS plaintext support go tls library, which refers to encrypted communication in https/tls programs written in the golang language.
Bash audit, capture bash command for Host Security Audit.
Zsh audit, capture zsh command for Host Security Audit.
MySQL query SQL audit, support mysqld 5.6\5.7\8.0, and MariaDB.

很有意思。

常规Capture举例

防止信息,过于冗长, 在关键位置, Capture执行,可有效过滤.

#ifndef ECAPTURE_GNUTLS_3_6_12_KERN_H
#define ECAPTURE_GNUTLS_3_6_12_KERN_H

// version 3.6.12, 3.6.13

// gnutls_session_int->security_parameters
#define GNUTLS_SESSION_INT_SECURITY_PARAMETERS 0x0

// gnutls_session_int->security_parameters.prf
#define GNUTLS_SESSION_INT_SECURITY_PARAMETERS_PRF 0x18

// mac_entry_st->id
#define MAC_ENTRY_ST_ID 0x18

// gnutls_session_int->security_parameters.client_random
#define GNUTLS_SESSION_INT_SECURITY_PARAMETERS_CLIENT_RANDOM 0x50

// gnutls_session_int->security_parameters.master_secret
#define GNUTLS_SESSION_INT_SECURITY_PARAMETERS_MASTER_SECRET 0x20

// gnutls_session_int->key.proto.tls13.hs_ckey
#define GNUTLS_SESSION_INT_KEY_PROTO_TLS13_HS_CKEY 0x14d4

// gnutls_session_int->key.proto.tls13.hs_skey
#define GNUTLS_SESSION_INT_KEY_PROTO_TLS13_HS_SKEY 0x1514

// gnutls_session_int->key.proto.tls13.ap_ckey
#define GNUTLS_SESSION_INT_KEY_PROTO_TLS13_AP_CKEY 0x1554

// gnutls_session_int->key.proto.tls13.ap_skey
#define GNUTLS_SESSION_INT_KEY_PROTO_TLS13_AP_SKEY 0x1594

// gnutls_session_int->key.proto.tls13.ap_expkey
#define GNUTLS_SESSION_INT_KEY_PROTO_TLS13_AP_EXPKEY 0x15d4

// security_parameters_st->pversion
#define SECURITY_PARAMETERS_ST_PVERSION 0xf8

// version_entry_st->id
#define VERSION_ENTRY_ST_ID 0x8

#include "gnutls.h"
#include "gnutls_masterkey.h"

#endif

常见参数说明

oriole:/data/local/tmp # ./ecapture100  --help                                                                                                                   
NAME:
        eCapture - Capturing SSL/TLS plaintext without a CA certificate using eBPF. Supported on Linux/Android kernels for amd64/arm64.

USAGE:
        eCapture [flags]

VERSION:
        androidgki_arm64:v1.0.0:6.8.0-1021-azure

COMMANDS:
        bash    capture bash command
        gotls   Capturing plaintext communication from Golang programs encrypted with TLS/HTTPS.
        help    Help about any command
        tls     Used to capture TLS/SSL text content without the need for a CA certificate. (Supports OpenSSL 1.0.x/1.1.x/3.x or newer).

DESCRIPTION:
        eCapture(旁观者) is a tool that can capture plaintext packets
        such as HTTPS and TLS without installing a CA certificate.
        It can also capture bash commands, which is suitable for
        security auditing scenarios, such as database auditing of mysqld, etc (disabled on Android).
        Support Linux(Android)  X86_64 4.18/aarch64 5.5 or newer.
        Repository: https://github.com/gojue/ecapture
        HomePage: https://ecapture.cc
        
        Usage:
          ecapture tls -h
          ecapture bash -h
        
        Docker usage:
        docker pull gojue/ecapture:latest
        docker run --rm --privileged=true --net=host -v ${HOST_PATH}:${CONTAINER_PATH} gojue/ecapture -h

OPTIONS:
  -b, --btf=0                           enable BTF mode.(0:auto; 1:core; 2:non-core)
  -d, --debug[=false]                   enable debug logging
      --eventaddr=""                    the server address that receives the captured event. --eventaddr tcp://127.0.0.1:8090, default: same as logaddr
  -h, --help[=false]                    help for eCapture
      --hex[=false]                     print byte strings as hex encoded strings
      --listen="localhost:28256"        listen on this address for http server, default: 127.0.0.1:28256
  -l, --logaddr=""                      send logs to this server. -l /tmp/ecapture.log or -l tcp://127.0.0.1:8080
      --mapsize=1024                    eBPF map size per CPU,for events buffer. default:1024 * PAGESIZE. (KB)
  -p, --pid=0                           if pid is 0 then we target all pids
  -t, --tsize=0                         the truncate size in text mode, default: 0 (B), no truncate
  -u, --uid=0                           if uid is 0 then we target all users
  -v, --version[=false]                 version for eCapture




oriole:/data/local/tmp # ./ecapture100  --help                                                                                                                   
NAME:
        eCapture - Capturing SSL/TLS plaintext without a CA certificate using eBPF. Supported on Linux/Android kernels for amd64/arm64.

USAGE:
        eCapture [flags]

VERSION:
        androidgki_arm64:v1.0.0:6.8.0-1021-azure

COMMANDS:
        bash    capture bash command
        gotls   Capturing plaintext communication from Golang programs encrypted with TLS/HTTPS.
        help    Help about any command
        tls     Used to capture TLS/SSL text content without the need for a CA certificate. (Supports OpenSSL 1.0.x/1.1.x/3.x or newer).

DESCRIPTION:
        eCapture(旁观者) is a tool that can capture plaintext packets
        such as HTTPS and TLS without installing a CA certificate.
        It can also capture bash commands, which is suitable for
        security auditing scenarios, such as database auditing of mysqld, etc (disabled on Android).
        Support Linux(Android)  X86_64 4.18/aarch64 5.5 or newer.
        Repository: https://github.com/gojue/ecapture
        HomePage: https://ecapture.cc
        
        Usage:
          ecapture tls -h
          ecapture bash -h
        
        Docker usage:
        docker pull gojue/ecapture:latest
        docker run --rm --privileged=true --net=host -v ${HOST_PATH}:${CONTAINER_PATH} gojue/ecapture -h

OPTIONS:
  -b, --btf=0                           enable BTF mode.(0:auto; 1:core; 2:non-core)
  -d, --debug[=false]                   enable debug logging
      --eventaddr=""                    the server address that receives the captured event. --eventaddr tcp://127.0.0.1:8090, default: same as logaddr
  -h, --help[=false]                    help for eCapture
      --hex[=false]                     print byte strings as hex encoded strings
      --listen="localhost:28256"        listen on this address for http server, default: 127.0.0.1:28256
  -l, --logaddr=""                      send logs to this server. -l /tmp/ecapture.log or -l tcp://127.0.0.1:8080
      --mapsize=1024                    eBPF map size per CPU,for events buffer. default:1024 * PAGESIZE. (KB)
  -p, --pid=0                           if pid is 0 then we target all pids
  -t, --tsize=0                         the truncate size in text mode, default: 0 (B), no truncate
  -u, --uid=0                           if uid is 0 then we target all users
  -v, --version[=false]                 version for eCapture

nocore.tar.gz 是4.18-5.10 之间的版本
aarch64.tar.gz 我们是支持的.

eBPF[13]:内核抓包核心原理

# ./ecapture tls -p 9076 --hex -l save.log
eBPF[13]:内核抓包核心原理

1F8B 就是 (使用了 Gzip的文件头) 进行 Encode. 压缩, 明文看不到.

下面看看 pcap 模式能否截获data.

# ./ecapture tls -p 9076 -m pcap -w save.pcapng
#  -i wlan0  这里把网卡关掉.
#  按照文档写的
// Copyright 2022 CFC4N <cfc4n.cs@gmail.com>. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/* Copyright © 2022 Hengqi Chen */
#include "ecapture.h"
#include "go_argument.h"
#include "tc.h"

#define GOTLS_RANDOM_SIZE 32

// max length is "CLIENT_HANDSHAKE_TRAFFIC_SECRET"=31
#define MASTER_SECRET_KEY_LEN 32
#define EVP_MAX_MD_SIZE 64
#define GOTLS_EVENT_TYPE_WRITE 0
#define GOTLS_EVENT_TYPE_READ 1

// // TLS record types in golang tls package
#define recordTypeApplicationData 23

struct go_tls_event {
    u64 ts_ns;
    u32 pid;
    u32 tid;
    s32 data_len;
    u8 event_type;
    char comm[TASK_COMM_LEN];
    char data[MAX_DATA_SIZE_OPENSSL];
};

struct mastersecret_gotls_t {
    u8 label[MASTER_SECRET_KEY_LEN];
    u8 labellen;
    u8 client_random[EVP_MAX_MD_SIZE];
    u8 client_random_len;
    u8 secret_[EVP_MAX_MD_SIZE];
    u8 secret_len;
};

/////////////////////////BPF MAPS ////////////////////////////////

// bpf map
struct {
    __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY);
    __uint(key_size, sizeof(u32));
    __uint(value_size, sizeof(u32));
    __uint(max_entries, 1024);
} mastersecret_go_events SEC(".maps");

struct {
    __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY);
    __uint(key_size, sizeof(u32));
    __uint(value_size, sizeof(u32));
    __uint(max_entries, 1024);
} events SEC(".maps");

struct {
    __uint(type, BPF_MAP_TYPE_LRU_HASH);
    __type(key, u64);
    __type(value, struct go_tls_event);
    __uint(max_entries, 2048);
} gte_context SEC(".maps");

struct {
    __uint(type, BPF_MAP_TYPE_ARRAY);
    __type(key, u32);
    __type(value, struct go_tls_event);
    __uint(max_entries, 1);
} gte_context_gen SEC(".maps");

static __always_inline struct go_tls_event *get_gotls_event() {
    u32 zero = 0;
    struct go_tls_event *event = bpf_map_lookup_elem(&gte_context_gen, &zero);
    if (!event) return 0;

    u64 id = bpf_get_current_pid_tgid();
    event->ts_ns = bpf_ktime_get_ns();
    event->pid = id >> 32;
    event->tid = (__u32)id;
    event->event_type = GOTLS_EVENT_TYPE_WRITE;
    bpf_get_current_comm(event->comm, sizeof(event->comm));
    bpf_map_update_elem(&gte_context, &id, event, BPF_ANY);
    return bpf_map_lookup_elem(&gte_context, &id);
}

static __always_inline int gotls_write(struct pt_regs *ctx, bool is_register_abi) {
    s32 record_type, len;
    const char *str;
    void *record_type_ptr;
    void *len_ptr;
    record_type_ptr = (void *)go_get_argument(ctx, is_register_abi, 2);
    bpf_probe_read_kernel(&record_type, sizeof(record_type), (void *)&record_type_ptr);
    str = (void *)go_get_argument(ctx, is_register_abi, 3);
    len_ptr = (void *)go_get_argument(ctx, is_register_abi, 4);
    bpf_probe_read_kernel(&len, sizeof(len), (void *)&len_ptr);

    if (len == 0) {
        return 0;
    }
    debug_bpf_printk("gotls_write record_type:%d, len:%d\n", record_type, len);
    if (record_type != recordTypeApplicationData) {
        return 0;
    }

    struct go_tls_event *event = get_gotls_event();
    if (!event) {
        return 0;
    }
    len = len & 0xFFFF;
    event->data_len = len;
    int ret = bpf_probe_read_user(&event->data, sizeof(event->data), (void *)str);
    if (ret < 0) {
        debug_bpf_printk("gotls_write bpf_probe_read_user_str failed, ret:%d, str:%d\n", ret, str);
        return 0;
    }
    bpf_perf_event_output(ctx, &events, BPF_F_CURRENT_CPU, event, sizeof(struct go_tls_event));
    return 0;
}

// capture golang tls plaintext, supported golang stack-based ABI (go version
// >= 1.17) type recordType uint8 writeRecordLocked(typ recordType, data []byte)
SEC("uprobe/gotls_write_register")
int gotls_write_register(struct pt_regs *ctx) { return gotls_write(ctx, true); }

// capture golang tls plaintext, supported golang stack-based ABI (go version
// < 1.17) type recordType uint8 writeRecordLocked(typ recordType, data []byte)
SEC("uprobe/gotls_write_stack")
int gotls_write_stack(struct pt_regs *ctx) { return gotls_write(ctx, false); }

// crypto/tls/conn.go
// func (c *Conn) Read(b []byte) (int, error)
static __always_inline int gotls_read(struct pt_regs *ctx, bool is_register_abi) {
    s32 record_type, ret_len;
    const char *str;
    void *len_ptr, *ret_len_ptr;

    // golang
    // uretprobe的实现,为选择目标函数中,汇编指令的RET指令地址,即调用子函数的返回后的触发点,此时,此函数参数等地址存放在SP(stack
    // Point)上,故使用stack方式读取
    // str 是 Golang TLS  *Conn.Read函数第一个参数b []byte的类型,对应runtime中

    str = (void *)go_get_argument(ctx, false, 2);
    if (is_register_abi) {
        ret_len_ptr = (void *)go_get_argument(ctx, is_register_abi, 1);
    } else {
        // by stack, Read函数的返回值第一个是int类型,存放在栈里的顺序是5
        ret_len_ptr = (void *)go_get_argument(ctx, is_register_abi, 5);
    }
    bpf_probe_read_kernel(&ret_len, sizeof(ret_len), (void *)&ret_len_ptr);
    debug_bpf_printk("gotls_read event, str:%p ret_len_ptr:%d, ret_len:%d\n", str, ret_len_ptr, ret_len);
    if (str <= 0) {
        return 0;
    }
    if (ret_len <= 0) {
        return 0;
    }

    struct go_tls_event *event = get_gotls_event();
    if (!event) {
        return 0;
    }

    event->data_len = ret_len;
    event->event_type = GOTLS_EVENT_TYPE_READ;
    int ret = bpf_probe_read_user(&event->data, sizeof(event->data), (void *)str);
    if (ret < 0) {
        debug_bpf_printk("gotls_text bpf_probe_read_user_str failed, ret:%d, str:%d\n", ret, str);
        return 0;
    }
    bpf_perf_event_output(ctx, &events, BPF_F_CURRENT_CPU, event, sizeof(struct go_tls_event));
    return 0;
}

// capture golang tls plaintext, supported golang stack-based ABI (go version
// < 1.17) func (c *Conn) Read(b []byte) (int, error)

SEC("uprobe/gotls_read_register")
int gotls_read_register(struct pt_regs *ctx) { return gotls_read(ctx, true); }

SEC("uprobe/gotls_read_stack")
int gotls_read_stack(struct pt_regs *ctx) { return gotls_read(ctx, false); }

/*
 * crypto/tls/common.go
 * func (c *Config) writeKeyLog(label string, clientRandom, secret []byte) error
 */
static __always_inline int gotls_mastersecret(struct pt_regs *ctx, bool is_register_abi) {
    //    const char *label, *clientrandom, *secret;
    void *lab_ptr, *cr_ptr, *secret_ptr;
    void *lab_len_ptr, *cr_len_ptr, *secret_len_ptr;
    s32 lab_len, cr_len, secret_len;

    /*
     *
     * in golang struct, slice header like this
     * type slice struct {
     * 	array unsafe.Pointer
     * 	len   int
     * 	cap   int
     * }
     * so, arument index are in the order one by one
     *
     */
    lab_ptr = (void *)go_get_argument(ctx, is_register_abi, 2);
    lab_len_ptr = (void *)go_get_argument(ctx, is_register_abi, 3);
    cr_ptr = (void *)go_get_argument(ctx, is_register_abi, 4);
    cr_len_ptr = (void *)go_get_argument(ctx, is_register_abi, 5);
    secret_ptr = (void *)go_get_argument(ctx, is_register_abi, 7);
    secret_len_ptr = (void *)go_get_argument(ctx, is_register_abi, 8);

    bpf_probe_read_kernel(&lab_len, sizeof(lab_len), (void *)&lab_len_ptr);
    bpf_probe_read_kernel(&cr_len, sizeof(lab_len), (void *)&cr_len_ptr);
    bpf_probe_read_kernel(&secret_len, sizeof(lab_len), (void *)&secret_len_ptr);

    if (lab_len <= 0 || cr_len <= 0 || secret_len <= 0) {
        return 0;
    }

    debug_bpf_printk(
        "gotls_mastersecret read params length success, lab_len:%d, cr_len:%d, "
        "secret_len:%d\n",
        lab_len, cr_len, secret_len);

    struct mastersecret_gotls_t mastersecret_gotls = {};
    mastersecret_gotls.labellen = lab_len;
    mastersecret_gotls.client_random_len = cr_len;
    mastersecret_gotls.secret_len = secret_len;
    int ret = bpf_probe_read_user_str(&mastersecret_gotls.label, sizeof(mastersecret_gotls.label), (void *)lab_ptr);
    if (ret < 0) {
        debug_bpf_printk(
            "gotls_mastersecret read mastersecret label failed, ret:%d, "
            "lab_ptr:%p\n",
            ret, lab_ptr);
        return 0;
    }

    debug_bpf_printk("gotls_mastersecret read mastersecret label:%s\n", mastersecret_gotls.label);
    ret = bpf_probe_read_user_str(&mastersecret_gotls.client_random, sizeof(mastersecret_gotls.client_random),
                                  (void *)cr_ptr);
    if (ret < 0) {
        debug_bpf_printk(
            "gotls_mastersecret read mastersecret client_random failed, "
            "ret:%d, cr_ptr:%p\n",
            ret, cr_ptr);
        return 0;
    }

    ret = bpf_probe_read_user_str(&mastersecret_gotls.secret_, sizeof(mastersecret_gotls.secret_), (void *)secret_ptr);
    if (ret < 0) {
        debug_bpf_printk(
            "gotls_mastersecret read mastersecret secret_ failed, ret:%d, "
            "secret_ptr:%p\n",
            ret, secret_ptr);
        return 0;
    }

    bpf_perf_event_output(ctx, &mastersecret_go_events, BPF_F_CURRENT_CPU, &mastersecret_gotls,
                          sizeof(struct mastersecret_gotls_t));
    return 0;
}

SEC("uprobe/gotls_mastersecret_register")
int gotls_mastersecret_register(struct pt_regs *ctx) { return gotls_mastersecret(ctx, true); }

SEC("uprobe/gotls_mastersecret_stack")
int gotls_mastersecret_stack(struct pt_regs *ctx) { return gotls_mastersecret(ctx, false); }

先删除原 save.pcapng 文件. rm save.pcapng

输入手机号, 验证码, 后, Activity 跳转到 “输入验证码” 页面, 再执行 capture 命令

输入code, 后, 点击登陆, get 数据 from server 时候 , 终止掉capture.

adb pull /data/local/tmp/save.pcapng
wireshark save.pcapng

eCapture 0.7.4 的pcap模式探索和wireshark分析

eBPF[13]:内核抓包核心原理

虽然可以想象我们所有人都可能实际生活在一个巨大且先进的计算机游戏中,但物理学家们的确被这样的想法所吸引,并且从理论上讲,它至少可以算是一种可能性。

其实除了马斯克,很多科技界领导人物都痴迷于模拟理论,并投资亿万美元进行研究。而苹果、谷歌和Facebook等企业扎堆的硅谷,更是站在这方面研究的最前沿。

在2016年,孵化器Y Combinator总裁Sam Altman的《纽约客》上表示,整个硅谷,包括他本人在内,都十分痴迷于计算机模拟这一概念。他说:“硅谷中很多人都十分痴迷于这种模拟假设,他们认为我们所体验的现实是计算机生成的。两位科技界的亿万富翁已经在偷偷招募科学家,希望能将我们从模拟中解放出来。”

在采访中,马斯克还重申了他对人工智能的严重关切,这个话题他曾公开谈论过多次。但对于人工智能所带来的风险,他感觉人们的态度仍不够重视。

他说,不够重视的其中一个表现是人们忽视人类和科技的融合,而这种融合却已经以惊人的速度在进行了。

“你已经是一个半机械人了。”他说,“iPhone其实就是你自己的延伸,只不过现在你与你所控制的延伸物品,例如手机和电脑,之间的沟通以及数据速率是缓慢的罢了。”

马斯克最新五大关注点:网络是ID的投影

在这场播客中,Rogan跟马斯克的两个半小时交谈,议题主要聚焦在五个方面:

1.人工智能的主要危险是人类把AI变成武器

马斯克早就对人工智能带来的危险提出了警告。今年3月,他在西南偏南上表示,人工智能远比核武器危险,政府应该采取行动,规范人工智能的发展。

马斯克说,主要的危险并不是人工智能对人类的攻击。“这里有个棘手的问题,那就是把人工智能作为武器是非常诱人的。危险在于人类互相使用它。”

在播客的另一部分中马斯克还补充道,“我试图说服人们放慢速度,减慢人工智能的速度,但这是徒劳的。我努力了很多年,没有人听。”

罗根也说,“这看起来就像电影里的一幕,机器人会他X的接管一切,而你把我吓坏了。”

“但是没人听”马斯克说。

2.很快就能宣布神经连接技术的重大进展

如果你不能打败AI,就加入AI。

这就是马斯克的基本论点。

他认为人工智能未来最好的情况就是找到人类与机器融合的方法。在某些方面,现在我们已经做到了:智能手机可以被视为人类自己的延伸。

但这种延伸与人工智能的关系存在带宽问题。

“你不能用手指交流,因为太慢了。”马斯克说。

我们的目标是大大改善我们的生物自我和数字自我之间的沟通渠道,这可以通过神经连接(neural-link)技术来实现,这种技术能帮助控制人类和人工智能的长期进化。

“从长期存在的角度来看,这就像神经连接的目的一样,是创造一个高带宽的大脑接口,这样我们就可以与人工智能共生。”

马斯克已经创办了Neuralink公司,至于这家公司的最新进展,他透露:“几个月后我们将会有一些有趣的事情宣布,至少比其他任何事情都好一个数量级,可能比任何人认为的都要好。”

他为这项技术描绘了一个长期愿景:给大脑添加人工认知的第三层“A.I. extension of yourself”——大脑皮层和大脑边缘系统形成共生关系。

3.社会正在与地球玩一场“疯狂的游戏”

马斯克表示,在向更可持续的能源转变的过程中,尽早实现电动汽车应该是重中之重。

“我们真的在玩一场关于大气和海洋的疯狂游戏。我们从地下深处收集了大量的碳,然后把这些碳释放在大气中,这是疯狂的。我们不应该这样做,这是非常危险的。我们应该加快向可持续能源的转变。很明显,从长远来看,我们会耗尽石油。我们开采和燃烧的石油只有这么多。我们必须有一个可持续的能源运输和能源基础设施。

我们从地下提取数万亿吨的碳,并将其排放到大气和海洋中。这是一个疯狂的实验。这是人类历史上最愚蠢的实验。我们为什么要这么做?这太疯狂了。”

4.网络景观是ID的投影

马斯克说,最成功的在线平台是那些与我们的大脑边缘系统产生共鸣的平台——大脑的一部分主要负责情感、刺激和记忆,而这些系统,比如社交媒体,则在整个社会的智能中所占的份额越来越大。

“想象一下所有这些事情,包括那种原始的动力,所有我们喜欢的、讨厌的、害怕的东西,都在互联网上,它们是我们大脑边缘系统的投影。”

5.一旦人工智能变得危险,监管它就太晚了

马斯克说,在政府真正开始监管一个行业之前,需要经过多年的规则制定和实施。以汽车行业的安全带法规为例,这一规定实际实施花了10年时间。

“这个时间框架与人工智能无关,从危险的时刻开始,你不可能(监管它)10年。太晚了。”

不过,当人工智能达到所谓的奇点时,会发生什么,谁也说不准。

“很难预测,就像黑洞一样,在视线之外会发生什么。它可能很可怕,也可能很伟大。目前还不清楚。有一件事是肯定的:我们控制不了它。”

马斯克也承认,他现在仍希望为人类做出最好的贡献。“比起相信正确但悲观的想法,我宁愿保持着错误但乐观的态度。”

最后再来说说抽烟喝酒玩大宝剑的事情。

在采访过程中,马斯克喝了威士忌后,也吸了一口大麻,但他说他并不喜欢经常这么做,因为这会令他引以为傲的效率降低。

“这就像倒上一杯咖啡,”马斯克说,“我喜欢把事情做好,也喜欢有用的事物。”

无论你爱他亦或恨他,你都不能否认马斯克有着这样一个有趣的观点。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

联系我们

联系我们

888-888-8888

在线咨询:点击这里给我发消息

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信
关注微信
分享本页
返回顶部